STM32L486xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l4xx_hal_sai.c 00004 * @author MCD Application Team 00005 * @brief SAI HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the Serial Audio Interface (SAI) peripheral: 00008 * + Initialization/de-initialization functions 00009 * + I/O operation functions 00010 * + Peripheral Control functions 00011 * + Peripheral State functions 00012 * 00013 @verbatim 00014 ============================================================================== 00015 ##### How to use this driver ##### 00016 ============================================================================== 00017 00018 [..] 00019 The SAI HAL driver can be used as follows: 00020 00021 (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai). 00022 (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API: 00023 (##) Enable the SAI interface clock. 00024 (##) SAI pins configuration: 00025 (+++) Enable the clock for the SAI GPIOs. 00026 (+++) Configure these SAI pins as alternate function pull-up. 00027 (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT() 00028 and HAL_SAI_Receive_IT() APIs): 00029 (+++) Configure the SAI interrupt priority. 00030 (+++) Enable the NVIC SAI IRQ handle. 00031 00032 (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA() 00033 and HAL_SAI_Receive_DMA() APIs): 00034 (+++) Declare a DMA handle structure for the Tx/Rx stream. 00035 (+++) Enable the DMAx interface clock. 00036 (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. 00037 (+++) Configure the DMA Tx/Rx Stream. 00038 (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle. 00039 (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the 00040 DMA Tx/Rx Stream. 00041 00042 (#) The initialization can be done by two ways 00043 (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init(). 00044 (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol(). 00045 00046 [..] 00047 (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt) 00048 will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT() 00049 inside the transmit and receive process. 00050 [..] 00051 (@) Make sure that either: 00052 (+@) PLLSAI1CLK output is configured or 00053 (+@) PLLSAI2CLK output is configured or 00054 (+@) PLLSAI3CLK output is configured or 00055 (+@) External clock source is configured after setting correctly 00056 the define constant EXTERNAL_SAI1_CLOCK_VALUE or EXTERNAL_SAI2_CLOCK_VALUE in the stm32l4xx_hal_conf.h file. 00057 00058 [..] 00059 (@) In master Tx mode: enabling the audio block immediately generates the bit clock 00060 for the external slaves even if there is no data in the FIFO, However FS signal 00061 generation is conditioned by the presence of data in the FIFO. 00062 00063 [..] 00064 (@) In master Rx mode: enabling the audio block immediately generates the bit clock 00065 and FS signal for the external slaves. 00066 00067 [..] 00068 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior: 00069 (+@) First bit Offset <= (SLOT size - Data size) 00070 (+@) Data size <= SLOT size 00071 (+@) Number of SLOT x SLOT size = Frame length 00072 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected. 00073 00074 [..] 00075 (@) For STM32L4Rx/STM32L4Sx devices, PDM interface can be activated through HAL_SAI_Init function. 00076 Please note that PDM interface is only available for SAI1 sub-block A. 00077 PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function. 00078 00079 [..] 00080 Three operation modes are available within this driver : 00081 00082 *** Polling mode IO operation *** 00083 ================================= 00084 [..] 00085 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit() 00086 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive() 00087 00088 *** Interrupt mode IO operation *** 00089 =================================== 00090 [..] 00091 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT() 00092 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 00093 add his own code by customization of function pointer HAL_SAI_TxCpltCallback() 00094 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT() 00095 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 00096 add his own code by customization of function pointer HAL_SAI_RxCpltCallback() 00097 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 00098 add his own code by customization of function pointer HAL_SAI_ErrorCallback() 00099 00100 *** DMA mode IO operation *** 00101 ============================= 00102 [..] 00103 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA() 00104 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can 00105 add his own code by customization of function pointer HAL_SAI_TxCpltCallback() 00106 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA() 00107 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can 00108 add his own code by customization of function pointer HAL_SAI_RxCpltCallback() 00109 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can 00110 add his own code by customization of function pointer HAL_SAI_ErrorCallback() 00111 (+) Pause the DMA Transfer using HAL_SAI_DMAPause() 00112 (+) Resume the DMA Transfer using HAL_SAI_DMAResume() 00113 (+) Stop the DMA Transfer using HAL_SAI_DMAStop() 00114 00115 *** SAI HAL driver additional function list *** 00116 =============================================== 00117 [..] 00118 Below the list the others API available SAI HAL driver : 00119 00120 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode 00121 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode 00122 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode 00123 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode 00124 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo. 00125 (+) HAL_SAI_Abort(): Abort the current transfer 00126 00127 *** SAI HAL driver macros list *** 00128 ================================== 00129 [..] 00130 Below the list of most used macros in SAI HAL driver : 00131 00132 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral 00133 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral 00134 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts 00135 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts 00136 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is 00137 enabled or disabled 00138 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not 00139 00140 *** Callback registration *** 00141 ============================= 00142 00143 The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1 00144 allows the user to configure dynamically the driver callbacks. 00145 Use functions @ref HAL_SAI_RegisterCallback() to register a user callback. 00146 00147 Function @ref HAL_SAI_RegisterCallback() allows to register following callbacks: 00148 (+) RxCpltCallback : SAI receive complete. 00149 (+) RxHalfCpltCallback : SAI receive half complete. 00150 (+) TxCpltCallback : SAI transmit complete. 00151 (+) TxHalfCpltCallback : SAI transmit half complete. 00152 (+) ErrorCallback : SAI error. 00153 (+) MspInitCallback : SAI MspInit. 00154 (+) MspDeInitCallback : SAI MspDeInit. 00155 This function takes as parameters the HAL peripheral handle, the callback ID 00156 and a pointer to the user callback function. 00157 00158 Use function @ref HAL_SAI_UnRegisterCallback() to reset a callback to the default 00159 weak (surcharged) function. 00160 @ref HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle, 00161 and the callback ID. 00162 This function allows to reset following callbacks: 00163 (+) RxCpltCallback : SAI receive complete. 00164 (+) RxHalfCpltCallback : SAI receive half complete. 00165 (+) TxCpltCallback : SAI transmit complete. 00166 (+) TxHalfCpltCallback : SAI transmit half complete. 00167 (+) ErrorCallback : SAI error. 00168 (+) MspInitCallback : SAI MspInit. 00169 (+) MspDeInitCallback : SAI MspDeInit. 00170 00171 By default, after the @ref HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET 00172 all callbacks are reset to the corresponding legacy weak (surcharged) functions: 00173 examples @ref HAL_SAI_RxCpltCallback(), @ref HAL_SAI_ErrorCallback(). 00174 Exception done for MspInit and MspDeInit callbacks that are respectively 00175 reset to the legacy weak (surcharged) functions in the @ref HAL_SAI_Init 00176 and @ref HAL_SAI_DeInit only when these callbacks are null (not registered beforehand). 00177 If not, MspInit or MspDeInit are not null, the @ref HAL_SAI_Init and @ref HAL_SAI_DeInit 00178 keep and use the user MspInit/MspDeInit callbacks (registered beforehand). 00179 00180 Callbacks can be registered/unregistered in READY state only. 00181 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered 00182 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used 00183 during the Init/DeInit. 00184 In that case first register the MspInit/MspDeInit user callbacks 00185 using @ref HAL_SAI_RegisterCallback before calling @ref HAL_SAI_DeInit 00186 or @ref HAL_SAI_Init function. 00187 00188 When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or 00189 not defined, the callback registering feature is not available 00190 and weak (surcharged) callbacks are used. 00191 00192 @endverbatim 00193 ****************************************************************************** 00194 * @attention 00195 * 00196 * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> 00197 * 00198 * Redistribution and use in source and binary forms, with or without modification, 00199 * are permitted provided that the following conditions are met: 00200 * 1. Redistributions of source code must retain the above copyright notice, 00201 * this list of conditions and the following disclaimer. 00202 * 2. Redistributions in binary form must reproduce the above copyright notice, 00203 * this list of conditions and the following disclaimer in the documentation 00204 * and/or other materials provided with the distribution. 00205 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00206 * may be used to endorse or promote products derived from this software 00207 * without specific prior written permission. 00208 * 00209 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00210 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00211 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00212 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00213 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00214 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00215 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00216 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00217 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00218 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00219 * 00220 ****************************************************************************** 00221 */ 00222 00223 /* Includes ------------------------------------------------------------------*/ 00224 #include "stm32l4xx_hal.h" 00225 00226 /** @addtogroup STM32L4xx_HAL_Driver 00227 * @{ 00228 */ 00229 00230 /** @defgroup SAI SAI 00231 * @brief SAI HAL module driver 00232 * @{ 00233 */ 00234 00235 #ifdef HAL_SAI_MODULE_ENABLED 00236 00237 /* Private typedef -----------------------------------------------------------*/ 00238 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs 00239 * @{ 00240 */ 00241 typedef enum 00242 { 00243 SAI_MODE_DMA, 00244 SAI_MODE_IT 00245 } SAI_ModeTypedef; 00246 /** 00247 * @} 00248 */ 00249 00250 /* Private define ------------------------------------------------------------*/ 00251 /** @defgroup SAI_Private_Constants SAI Private Constants 00252 * @{ 00253 */ 00254 #define SAI_FIFO_SIZE 8 00255 #define SAI_DEFAULT_TIMEOUT 4U 00256 #define SAI_LONG_TIMEOUT 1000U 00257 /** 00258 * @} 00259 */ 00260 00261 /* Private macro -------------------------------------------------------------*/ 00262 /* Private variables ---------------------------------------------------------*/ 00263 /* Private function prototypes -----------------------------------------------*/ 00264 /** @defgroup SAI_Private_Functions SAI Private Functions 00265 * @{ 00266 */ 00267 static void SAI_FillFifo(SAI_HandleTypeDef *hsai); 00268 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode); 00269 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); 00270 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); 00271 00272 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai); 00273 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai); 00274 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai); 00275 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai); 00276 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai); 00277 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai); 00278 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai); 00279 00280 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma); 00281 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma); 00282 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma); 00283 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma); 00284 static void SAI_DMAError(DMA_HandleTypeDef *hdma); 00285 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma); 00286 /** 00287 * @} 00288 */ 00289 00290 /* Exported functions ---------------------------------------------------------*/ 00291 /** @defgroup SAI_Exported_Functions SAI Exported Functions 00292 * @{ 00293 */ 00294 00295 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions 00296 * @brief Initialization and Configuration functions 00297 * 00298 @verbatim 00299 =============================================================================== 00300 ##### Initialization and de-initialization functions ##### 00301 =============================================================================== 00302 [..] This subsection provides a set of functions allowing to initialize and 00303 de-initialize the SAIx peripheral: 00304 00305 (+) User must implement HAL_SAI_MspInit() function in which he configures 00306 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). 00307 00308 (+) Call the function HAL_SAI_Init() to configure the selected device with 00309 the selected configuration: 00310 (++) Mode (Master/slave TX/RX) 00311 (++) Protocol 00312 (++) Data Size 00313 (++) MCLK Output 00314 (++) Audio frequency 00315 (++) FIFO Threshold 00316 (++) Frame Config 00317 (++) Slot Config 00318 (++) PDM Config (only for STM32L4Rx/STM32L4Sx devices) 00319 00320 (+) Call the function HAL_SAI_DeInit() to restore the default configuration 00321 of the selected SAI peripheral. 00322 00323 @endverbatim 00324 * @{ 00325 */ 00326 00327 /** 00328 * @brief Initialize the structure FrameInit, SlotInit and the low part of 00329 * Init according to the specified parameters and call the function 00330 * HAL_SAI_Init to initialize the SAI block. 00331 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00332 * the configuration information for SAI module. 00333 * @param protocol one of the supported protocol @ref SAI_Protocol 00334 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize 00335 * the configuration information for SAI module. 00336 * @param nbslot Number of slot. 00337 * @retval HAL status 00338 */ 00339 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 00340 { 00341 HAL_StatusTypeDef status; 00342 00343 /* Check the parameters */ 00344 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol)); 00345 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize)); 00346 00347 switch (protocol) 00348 { 00349 case SAI_I2S_STANDARD : 00350 case SAI_I2S_MSBJUSTIFIED : 00351 case SAI_I2S_LSBJUSTIFIED : 00352 status = SAI_InitI2S(hsai, protocol, datasize, nbslot); 00353 break; 00354 case SAI_PCM_LONG : 00355 case SAI_PCM_SHORT : 00356 status = SAI_InitPCM(hsai, protocol, datasize, nbslot); 00357 break; 00358 default : 00359 status = HAL_ERROR; 00360 break; 00361 } 00362 00363 if (status == HAL_OK) 00364 { 00365 status = HAL_SAI_Init(hsai); 00366 } 00367 00368 return status; 00369 } 00370 00371 /** 00372 * @brief Initialize the SAI according to the specified parameters. 00373 * in the SAI_InitTypeDef structure and initialize the associated handle. 00374 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00375 * the configuration information for SAI module. 00376 * @retval HAL status 00377 */ 00378 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai) 00379 { 00380 uint32_t tmpregisterGCR; 00381 uint32_t ckstr_bits; 00382 uint32_t syncen_bits; 00383 00384 /* Check the SAI handle allocation */ 00385 if (hsai == NULL) 00386 { 00387 return HAL_ERROR; 00388 } 00389 00390 /* check the instance */ 00391 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance)); 00392 00393 /* Check the SAI Block parameters */ 00394 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency)); 00395 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol)); 00396 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode)); 00397 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize)); 00398 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit)); 00399 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing)); 00400 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro)); 00401 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive)); 00402 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider)); 00403 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold)); 00404 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode)); 00405 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode)); 00406 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState)); 00407 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt)); 00408 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00409 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling)); 00410 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00411 00412 /* Check the SAI Block Frame parameters */ 00413 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength)); 00414 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength)); 00415 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition)); 00416 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity)); 00417 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset)); 00418 00419 /* Check the SAI Block Slot parameters */ 00420 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset)); 00421 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize)); 00422 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber)); 00423 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive)); 00424 00425 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00426 /* Check the SAI PDM parameters */ 00427 assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation)); 00428 if (hsai->Init.PdmInit.Activation == ENABLE) 00429 { 00430 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr)); 00431 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable)); 00432 /* Check that SAI sub-block is SAI1 sub-block A, in master RX mode with free protocol */ 00433 if ((hsai->Instance != SAI1_Block_A) || 00434 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) || 00435 (hsai->Init.Protocol != SAI_FREE_PROTOCOL)) 00436 { 00437 return HAL_ERROR; 00438 } 00439 } 00440 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00441 00442 if (hsai->State == HAL_SAI_STATE_RESET) 00443 { 00444 /* Allocate lock resource and initialize it */ 00445 hsai->Lock = HAL_UNLOCKED; 00446 00447 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 00448 /* Reset callback pointers to the weak predefined callbacks */ 00449 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback; 00450 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback; 00451 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback; 00452 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback; 00453 hsai->ErrorCallback = HAL_SAI_ErrorCallback; 00454 00455 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ 00456 if (hsai->MspInitCallback == NULL) 00457 { 00458 hsai->MspInitCallback = HAL_SAI_MspInit; 00459 } 00460 hsai->MspInitCallback(hsai); 00461 #else 00462 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ 00463 HAL_SAI_MspInit(hsai); 00464 #endif 00465 } 00466 00467 /* Disable the selected SAI peripheral */ 00468 if (SAI_Disable(hsai) != HAL_OK) 00469 { 00470 return HAL_ERROR; 00471 } 00472 00473 hsai->State = HAL_SAI_STATE_BUSY; 00474 00475 /* SAI Block Synchro Configuration -----------------------------------------*/ 00476 /* This setting must be done with both audio block (A & B) disabled */ 00477 switch (hsai->Init.SynchroExt) 00478 { 00479 case SAI_SYNCEXT_DISABLE : 00480 tmpregisterGCR = 0; 00481 break; 00482 case SAI_SYNCEXT_OUTBLOCKA_ENABLE : 00483 tmpregisterGCR = SAI_GCR_SYNCOUT_0; 00484 break; 00485 case SAI_SYNCEXT_OUTBLOCKB_ENABLE : 00486 tmpregisterGCR = SAI_GCR_SYNCOUT_1; 00487 break; 00488 default : 00489 tmpregisterGCR = 0; 00490 break; 00491 } 00492 00493 switch (hsai->Init.Synchro) 00494 { 00495 case SAI_ASYNCHRONOUS : 00496 syncen_bits = 0; 00497 break; 00498 case SAI_SYNCHRONOUS : 00499 syncen_bits = SAI_xCR1_SYNCEN_0; 00500 break; 00501 case SAI_SYNCHRONOUS_EXT_SAI1 : 00502 syncen_bits = SAI_xCR1_SYNCEN_1; 00503 break; 00504 case SAI_SYNCHRONOUS_EXT_SAI2 : 00505 syncen_bits = SAI_xCR1_SYNCEN_1; 00506 tmpregisterGCR |= SAI_GCR_SYNCIN_0; 00507 break; 00508 default : 00509 syncen_bits = 0; 00510 break; 00511 } 00512 00513 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ 00514 defined(STM32L496xx) || defined(STM32L4A6xx) || \ 00515 defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00516 00517 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) 00518 { 00519 SAI1->GCR = tmpregisterGCR; 00520 } 00521 else 00522 { 00523 SAI2->GCR = tmpregisterGCR; 00524 } 00525 00526 #else 00527 00528 SAI1->GCR = tmpregisterGCR; 00529 00530 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ 00531 /* STM32L496xx || STM32L4A6xx || */ 00532 /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00533 00534 if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV) 00535 { 00536 uint32_t freq; 00537 uint32_t tmpval; 00538 00539 /* In this case, the MCKDIV value is calculated to get AudioFrequency */ 00540 #if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ 00541 defined(STM32L496xx) || defined(STM32L4A6xx) || \ 00542 defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00543 00544 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) 00545 { 00546 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); 00547 } 00548 else 00549 { 00550 /* SAI2_Block_A or SAI2_Block_B */ 00551 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2); 00552 } 00553 00554 #else 00555 00556 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); 00557 00558 #endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ 00559 /* STM32L496xx || STM32L4A6xx || */ 00560 /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00561 00562 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00563 /* Configure Master Clock Divider using the following formula : 00564 - If NOMCK = 1 : 00565 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1)) 00566 - If NOMCK = 0 : 00567 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */ 00568 if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE) 00569 { 00570 /* NOMCK = 1 */ 00571 /* (freq x 10) to keep Significant digits */ 00572 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * hsai->FrameInit.FrameLength); 00573 } 00574 else 00575 { 00576 /* NOMCK = 0 */ 00577 uint32_t tmposr; 00578 tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U; 00579 /* (freq x 10) to keep Significant digits */ 00580 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U); 00581 } 00582 hsai->Init.Mckdiv = tmpval / 10U; 00583 00584 /* Round result to the nearest integer */ 00585 if ((tmpval % 10U) > 8U) 00586 { 00587 hsai->Init.Mckdiv += 1U; 00588 } 00589 #else 00590 /* Configure Master Clock using the following formula : 00591 MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS 00592 FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256 00593 MCKDIV[3:0] = SAI_CK_x / FS * 512 */ 00594 /* (freq x 10) to keep Significant digits */ 00595 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * 2U * 256U); 00596 hsai->Init.Mckdiv = tmpval / 10U; 00597 00598 /* Round result to the nearest integer */ 00599 if ((tmpval % 10U) > 8U) 00600 { 00601 hsai->Init.Mckdiv += 1U; 00602 } 00603 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00604 } 00605 00606 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */ 00607 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 00608 { 00609 /* Transmit */ 00610 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR; 00611 } 00612 else 00613 { 00614 /* Receive */ 00615 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U; 00616 } 00617 00618 /* SAI Block Configuration -------------------------------------------------*/ 00619 /* SAI CR1 Configuration */ 00620 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00621 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \ 00622 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \ 00623 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \ 00624 SAI_xCR1_NOMCK | SAI_xCR1_MCKDIV | SAI_xCR1_OSR); 00625 00626 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \ 00627 hsai->Init.DataSize | hsai->Init.FirstBit | \ 00628 ckstr_bits | syncen_bits | \ 00629 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \ 00630 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \ 00631 hsai->Init.MckOverSampling); 00632 #else 00633 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \ 00634 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \ 00635 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \ 00636 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV); 00637 00638 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \ 00639 hsai->Init.DataSize | hsai->Init.FirstBit | \ 00640 ckstr_bits | syncen_bits | \ 00641 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \ 00642 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20)); 00643 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00644 00645 /* SAI CR2 Configuration */ 00646 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL); 00647 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState); 00648 00649 /* SAI Frame Configuration -----------------------------------------*/ 00650 hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \ 00651 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF)); 00652 hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) | 00653 hsai->FrameInit.FSOffset | 00654 hsai->FrameInit.FSDefinition | 00655 hsai->FrameInit.FSPolarity | 00656 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8)); 00657 00658 /* SAI Block_x SLOT Configuration ------------------------------------------*/ 00659 /* This register has no meaning in AC 97 and SPDIF audio protocol */ 00660 hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \ 00661 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN)); 00662 00663 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \ 00664 (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8); 00665 00666 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00667 /* SAI PDM Configuration ---------------------------------------------------*/ 00668 if (hsai->Instance == SAI1_Block_A) 00669 { 00670 /* Disable PDM interface */ 00671 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN); 00672 if (hsai->Init.PdmInit.Activation == ENABLE) 00673 { 00674 /* Configure and enable PDM interface */ 00675 SAI1->PDMCR = (hsai->Init.PdmInit.ClockEnable | 00676 ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos)); 00677 SAI1->PDMCR |= SAI_PDMCR_PDMEN; 00678 } 00679 } 00680 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00681 00682 /* Initialize the error code */ 00683 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00684 00685 /* Initialize the SAI state */ 00686 hsai->State = HAL_SAI_STATE_READY; 00687 00688 /* Release Lock */ 00689 __HAL_UNLOCK(hsai); 00690 00691 return HAL_OK; 00692 } 00693 00694 /** 00695 * @brief DeInitialize the SAI peripheral. 00696 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00697 * the configuration information for SAI module. 00698 * @retval HAL status 00699 */ 00700 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai) 00701 { 00702 /* Check the SAI handle allocation */ 00703 if (hsai == NULL) 00704 { 00705 return HAL_ERROR; 00706 } 00707 00708 hsai->State = HAL_SAI_STATE_BUSY; 00709 00710 /* Disabled All interrupt and clear all the flag */ 00711 hsai->Instance->IMR = 0; 00712 hsai->Instance->CLRFR = 0xFFFFFFFFU; 00713 00714 /* Disable the SAI */ 00715 if (SAI_Disable(hsai) != HAL_OK) 00716 { 00717 /* Reset SAI state to ready */ 00718 hsai->State = HAL_SAI_STATE_READY; 00719 00720 /* Release Lock */ 00721 __HAL_UNLOCK(hsai); 00722 00723 return HAL_ERROR; 00724 } 00725 00726 /* Flush the fifo */ 00727 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 00728 00729 #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) 00730 /* Disable SAI PDM interface */ 00731 if (hsai->Instance == SAI1_Block_A) 00732 { 00733 /* Reset PDM delays */ 00734 SAI1->PDMDLY = 0U; 00735 00736 /* Disable PDM interface */ 00737 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN); 00738 } 00739 #endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 00740 00741 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ 00742 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 00743 if (hsai->MspDeInitCallback == NULL) 00744 { 00745 hsai->MspDeInitCallback = HAL_SAI_MspDeInit; 00746 } 00747 hsai->MspDeInitCallback(hsai); 00748 #else 00749 HAL_SAI_MspDeInit(hsai); 00750 #endif 00751 00752 /* Initialize the error code */ 00753 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 00754 00755 /* Initialize the SAI state */ 00756 hsai->State = HAL_SAI_STATE_RESET; 00757 00758 /* Release Lock */ 00759 __HAL_UNLOCK(hsai); 00760 00761 return HAL_OK; 00762 } 00763 00764 /** 00765 * @brief Initialize the SAI MSP. 00766 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00767 * the configuration information for SAI module. 00768 * @retval None 00769 */ 00770 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) 00771 { 00772 /* Prevent unused argument(s) compilation warning */ 00773 UNUSED(hsai); 00774 00775 /* NOTE : This function should not be modified, when the callback is needed, 00776 the HAL_SAI_MspInit could be implemented in the user file 00777 */ 00778 } 00779 00780 /** 00781 * @brief DeInitialize the SAI MSP. 00782 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 00783 * the configuration information for SAI module. 00784 * @retval None 00785 */ 00786 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai) 00787 { 00788 /* Prevent unused argument(s) compilation warning */ 00789 UNUSED(hsai); 00790 00791 /* NOTE : This function should not be modified, when the callback is needed, 00792 the HAL_SAI_MspDeInit could be implemented in the user file 00793 */ 00794 } 00795 00796 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 00797 /** 00798 * @brief Register a user SAI callback 00799 * to be used instead of the weak predefined callback. 00800 * @param hsai SAI handle. 00801 * @param CallbackID ID of the callback to be registered. 00802 * This parameter can be one of the following values: 00803 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID. 00804 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. 00805 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID. 00806 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. 00807 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID. 00808 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID. 00809 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID. 00810 * @param pCallback pointer to the callback function. 00811 * @retval HAL status. 00812 */ 00813 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai, 00814 HAL_SAI_CallbackIDTypeDef CallbackID, 00815 pSAI_CallbackTypeDef pCallback) 00816 { 00817 HAL_StatusTypeDef status = HAL_OK; 00818 00819 if (pCallback == NULL) 00820 { 00821 /* update the error code */ 00822 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00823 /* update return status */ 00824 status = HAL_ERROR; 00825 } 00826 else 00827 { 00828 if (HAL_SAI_STATE_READY == hsai->State) 00829 { 00830 switch (CallbackID) 00831 { 00832 case HAL_SAI_RX_COMPLETE_CB_ID : 00833 hsai->RxCpltCallback = pCallback; 00834 break; 00835 case HAL_SAI_RX_HALFCOMPLETE_CB_ID : 00836 hsai->RxHalfCpltCallback = pCallback; 00837 break; 00838 case HAL_SAI_TX_COMPLETE_CB_ID : 00839 hsai->TxCpltCallback = pCallback; 00840 break; 00841 case HAL_SAI_TX_HALFCOMPLETE_CB_ID : 00842 hsai->TxHalfCpltCallback = pCallback; 00843 break; 00844 case HAL_SAI_ERROR_CB_ID : 00845 hsai->ErrorCallback = pCallback; 00846 break; 00847 case HAL_SAI_MSPINIT_CB_ID : 00848 hsai->MspInitCallback = pCallback; 00849 break; 00850 case HAL_SAI_MSPDEINIT_CB_ID : 00851 hsai->MspDeInitCallback = pCallback; 00852 break; 00853 default : 00854 /* update the error code */ 00855 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00856 /* update return status */ 00857 status = HAL_ERROR; 00858 break; 00859 } 00860 } 00861 else if (HAL_SAI_STATE_RESET == hsai->State) 00862 { 00863 switch (CallbackID) 00864 { 00865 case HAL_SAI_MSPINIT_CB_ID : 00866 hsai->MspInitCallback = pCallback; 00867 break; 00868 case HAL_SAI_MSPDEINIT_CB_ID : 00869 hsai->MspDeInitCallback = pCallback; 00870 break; 00871 default : 00872 /* update the error code */ 00873 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00874 /* update return status */ 00875 status = HAL_ERROR; 00876 break; 00877 } 00878 } 00879 else 00880 { 00881 /* update the error code */ 00882 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00883 /* update return status */ 00884 status = HAL_ERROR; 00885 } 00886 } 00887 return status; 00888 } 00889 00890 /** 00891 * @brief Unregister a user SAI callback. 00892 * SAI callback is redirected to the weak predefined callback. 00893 * @param hsai SAI handle. 00894 * @param CallbackID ID of the callback to be unregistered. 00895 * This parameter can be one of the following values: 00896 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID. 00897 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. 00898 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID. 00899 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. 00900 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID. 00901 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID. 00902 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID. 00903 * @retval HAL status. 00904 */ 00905 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai, 00906 HAL_SAI_CallbackIDTypeDef CallbackID) 00907 { 00908 HAL_StatusTypeDef status = HAL_OK; 00909 00910 if (HAL_SAI_STATE_READY == hsai->State) 00911 { 00912 switch (CallbackID) 00913 { 00914 case HAL_SAI_RX_COMPLETE_CB_ID : 00915 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback; 00916 break; 00917 case HAL_SAI_RX_HALFCOMPLETE_CB_ID : 00918 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback; 00919 break; 00920 case HAL_SAI_TX_COMPLETE_CB_ID : 00921 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback; 00922 break; 00923 case HAL_SAI_TX_HALFCOMPLETE_CB_ID : 00924 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback; 00925 break; 00926 case HAL_SAI_ERROR_CB_ID : 00927 hsai->ErrorCallback = HAL_SAI_ErrorCallback; 00928 break; 00929 case HAL_SAI_MSPINIT_CB_ID : 00930 hsai->MspInitCallback = HAL_SAI_MspInit; 00931 break; 00932 case HAL_SAI_MSPDEINIT_CB_ID : 00933 hsai->MspDeInitCallback = HAL_SAI_MspDeInit; 00934 break; 00935 default : 00936 /* update the error code */ 00937 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00938 /* update return status */ 00939 status = HAL_ERROR; 00940 break; 00941 } 00942 } 00943 else if (HAL_SAI_STATE_RESET == hsai->State) 00944 { 00945 switch (CallbackID) 00946 { 00947 case HAL_SAI_MSPINIT_CB_ID : 00948 hsai->MspInitCallback = HAL_SAI_MspInit; 00949 break; 00950 case HAL_SAI_MSPDEINIT_CB_ID : 00951 hsai->MspDeInitCallback = HAL_SAI_MspDeInit; 00952 break; 00953 default : 00954 /* update the error code */ 00955 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00956 /* update return status */ 00957 status = HAL_ERROR; 00958 break; 00959 } 00960 } 00961 else 00962 { 00963 /* update the error code */ 00964 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; 00965 /* update return status */ 00966 status = HAL_ERROR; 00967 } 00968 return status; 00969 } 00970 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ 00971 00972 /** 00973 * @} 00974 */ 00975 00976 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions 00977 * @brief Data transfers functions 00978 * 00979 @verbatim 00980 ============================================================================== 00981 ##### IO operation functions ##### 00982 ============================================================================== 00983 [..] 00984 This subsection provides a set of functions allowing to manage the SAI data 00985 transfers. 00986 00987 (+) There are two modes of transfer: 00988 (++) Blocking mode : The communication is performed in the polling mode. 00989 The status of all data processing is returned by the same function 00990 after finishing transfer. 00991 (++) No-Blocking mode : The communication is performed using Interrupts 00992 or DMA. These functions return the status of the transfer startup. 00993 The end of the data processing will be indicated through the 00994 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when 00995 using DMA mode. 00996 00997 (+) Blocking mode functions are : 00998 (++) HAL_SAI_Transmit() 00999 (++) HAL_SAI_Receive() 01000 01001 (+) Non Blocking mode functions with Interrupt are : 01002 (++) HAL_SAI_Transmit_IT() 01003 (++) HAL_SAI_Receive_IT() 01004 01005 (+) Non Blocking mode functions with DMA are : 01006 (++) HAL_SAI_Transmit_DMA() 01007 (++) HAL_SAI_Receive_DMA() 01008 01009 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode: 01010 (++) HAL_SAI_TxCpltCallback() 01011 (++) HAL_SAI_RxCpltCallback() 01012 (++) HAL_SAI_ErrorCallback() 01013 01014 @endverbatim 01015 * @{ 01016 */ 01017 01018 /** 01019 * @brief Transmit an amount of data in blocking mode. 01020 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01021 * the configuration information for SAI module. 01022 * @param pData Pointer to data buffer 01023 * @param Size Amount of data to be sent 01024 * @param Timeout Timeout duration 01025 * @retval HAL status 01026 */ 01027 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout) 01028 { 01029 uint32_t tickstart = HAL_GetTick(); 01030 uint32_t temp; 01031 01032 if ((pData == NULL) || (Size == 0U)) 01033 { 01034 return HAL_ERROR; 01035 } 01036 01037 if (hsai->State == HAL_SAI_STATE_READY) 01038 { 01039 /* Process Locked */ 01040 __HAL_LOCK(hsai); 01041 01042 hsai->XferSize = Size; 01043 hsai->XferCount = Size; 01044 hsai->pBuffPtr = pData; 01045 hsai->State = HAL_SAI_STATE_BUSY_TX; 01046 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01047 01048 /* Check if the SAI is already enabled */ 01049 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01050 { 01051 /* fill the fifo with data before to enabled the SAI */ 01052 SAI_FillFifo(hsai); 01053 /* Enable SAI peripheral */ 01054 __HAL_SAI_ENABLE(hsai); 01055 } 01056 01057 while (hsai->XferCount > 0U) 01058 { 01059 /* Write data if the FIFO is not full */ 01060 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) 01061 { 01062 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 01063 { 01064 hsai->Instance->DR = *hsai->pBuffPtr; 01065 hsai->pBuffPtr++; 01066 } 01067 else if (hsai->Init.DataSize <= SAI_DATASIZE_16) 01068 { 01069 temp = (uint32_t)(*hsai->pBuffPtr); 01070 hsai->pBuffPtr++; 01071 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 01072 hsai->pBuffPtr++; 01073 hsai->Instance->DR = temp; 01074 } 01075 else 01076 { 01077 temp = (uint32_t)(*hsai->pBuffPtr); 01078 hsai->pBuffPtr++; 01079 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 01080 hsai->pBuffPtr++; 01081 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16); 01082 hsai->pBuffPtr++; 01083 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24); 01084 hsai->pBuffPtr++; 01085 hsai->Instance->DR = temp; 01086 } 01087 hsai->XferCount--; 01088 } 01089 else 01090 { 01091 /* Check for the Timeout */ 01092 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY)) 01093 { 01094 /* Update error code */ 01095 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 01096 01097 /* Clear all the flags */ 01098 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01099 01100 /* Disable SAI peripheral */ 01101 if (SAI_Disable(hsai) != HAL_OK) 01102 { 01103 /* Nothing to do because state update, unlock and error return will be performed later */ 01104 } 01105 01106 /* Flush the fifo */ 01107 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01108 01109 /* Change the SAI state */ 01110 hsai->State = HAL_SAI_STATE_READY; 01111 01112 /* Process Unlocked */ 01113 __HAL_UNLOCK(hsai); 01114 01115 return HAL_ERROR; 01116 } 01117 } 01118 } 01119 01120 hsai->State = HAL_SAI_STATE_READY; 01121 01122 /* Process Unlocked */ 01123 __HAL_UNLOCK(hsai); 01124 01125 return HAL_OK; 01126 } 01127 else 01128 { 01129 return HAL_BUSY; 01130 } 01131 } 01132 01133 /** 01134 * @brief Receive an amount of data in blocking mode. 01135 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01136 * the configuration information for SAI module. 01137 * @param pData Pointer to data buffer 01138 * @param Size Amount of data to be received 01139 * @param Timeout Timeout duration 01140 * @retval HAL status 01141 */ 01142 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout) 01143 { 01144 uint32_t tickstart = HAL_GetTick(); 01145 uint32_t temp; 01146 01147 if ((pData == NULL) || (Size == 0U)) 01148 { 01149 return HAL_ERROR; 01150 } 01151 01152 if (hsai->State == HAL_SAI_STATE_READY) 01153 { 01154 /* Process Locked */ 01155 __HAL_LOCK(hsai); 01156 01157 hsai->pBuffPtr = pData; 01158 hsai->XferSize = Size; 01159 hsai->XferCount = Size; 01160 hsai->State = HAL_SAI_STATE_BUSY_RX; 01161 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01162 01163 /* Check if the SAI is already enabled */ 01164 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01165 { 01166 /* Enable SAI peripheral */ 01167 __HAL_SAI_ENABLE(hsai); 01168 } 01169 01170 /* Receive data */ 01171 while (hsai->XferCount > 0U) 01172 { 01173 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY) 01174 { 01175 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 01176 { 01177 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR; 01178 hsai->pBuffPtr++; 01179 } 01180 else if (hsai->Init.DataSize <= SAI_DATASIZE_16) 01181 { 01182 temp = hsai->Instance->DR; 01183 *hsai->pBuffPtr = (uint8_t)temp; 01184 hsai->pBuffPtr++; 01185 *hsai->pBuffPtr = (uint8_t)(temp >> 8); 01186 hsai->pBuffPtr++; 01187 } 01188 else 01189 { 01190 temp = hsai->Instance->DR; 01191 *hsai->pBuffPtr = (uint8_t)temp; 01192 hsai->pBuffPtr++; 01193 *hsai->pBuffPtr = (uint8_t)(temp >> 8); 01194 hsai->pBuffPtr++; 01195 *hsai->pBuffPtr = (uint8_t)(temp >> 16); 01196 hsai->pBuffPtr++; 01197 *hsai->pBuffPtr = (uint8_t)(temp >> 24); 01198 hsai->pBuffPtr++; 01199 } 01200 hsai->XferCount--; 01201 } 01202 else 01203 { 01204 /* Check for the Timeout */ 01205 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY)) 01206 { 01207 /* Update error code */ 01208 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 01209 01210 /* Clear all the flags */ 01211 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01212 01213 /* Disable SAI peripheral */ 01214 if (SAI_Disable(hsai) != HAL_OK) 01215 { 01216 /* Nothing to do because state update, unlock and error return will be performed later */ 01217 } 01218 01219 /* Flush the fifo */ 01220 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01221 01222 /* Change the SAI state */ 01223 hsai->State = HAL_SAI_STATE_READY; 01224 01225 /* Process Unlocked */ 01226 __HAL_UNLOCK(hsai); 01227 01228 return HAL_ERROR; 01229 } 01230 } 01231 } 01232 01233 hsai->State = HAL_SAI_STATE_READY; 01234 01235 /* Process Unlocked */ 01236 __HAL_UNLOCK(hsai); 01237 01238 return HAL_OK; 01239 } 01240 else 01241 { 01242 return HAL_BUSY; 01243 } 01244 } 01245 01246 /** 01247 * @brief Transmit an amount of data in non-blocking mode with Interrupt. 01248 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01249 * the configuration information for SAI module. 01250 * @param pData Pointer to data buffer 01251 * @param Size Amount of data to be sent 01252 * @retval HAL status 01253 */ 01254 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01255 { 01256 if ((pData == NULL) || (Size == 0U)) 01257 { 01258 return HAL_ERROR; 01259 } 01260 01261 if (hsai->State == HAL_SAI_STATE_READY) 01262 { 01263 /* Process Locked */ 01264 __HAL_LOCK(hsai); 01265 01266 hsai->pBuffPtr = pData; 01267 hsai->XferSize = Size; 01268 hsai->XferCount = Size; 01269 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01270 hsai->State = HAL_SAI_STATE_BUSY_TX; 01271 01272 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 01273 { 01274 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit; 01275 } 01276 else if (hsai->Init.DataSize <= SAI_DATASIZE_16) 01277 { 01278 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit; 01279 } 01280 else 01281 { 01282 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit; 01283 } 01284 01285 /* Fill the fifo before starting the communication */ 01286 SAI_FillFifo(hsai); 01287 01288 /* Enable FRQ and OVRUDR interrupts */ 01289 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01290 01291 /* Check if the SAI is already enabled */ 01292 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01293 { 01294 /* Enable SAI peripheral */ 01295 __HAL_SAI_ENABLE(hsai); 01296 } 01297 /* Process Unlocked */ 01298 __HAL_UNLOCK(hsai); 01299 01300 return HAL_OK; 01301 } 01302 else 01303 { 01304 return HAL_BUSY; 01305 } 01306 } 01307 01308 /** 01309 * @brief Receive an amount of data in non-blocking mode with Interrupt. 01310 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01311 * the configuration information for SAI module. 01312 * @param pData Pointer to data buffer 01313 * @param Size Amount of data to be received 01314 * @retval HAL status 01315 */ 01316 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01317 { 01318 if ((pData == NULL) || (Size == 0U)) 01319 { 01320 return HAL_ERROR; 01321 } 01322 01323 if (hsai->State == HAL_SAI_STATE_READY) 01324 { 01325 /* Process Locked */ 01326 __HAL_LOCK(hsai); 01327 01328 hsai->pBuffPtr = pData; 01329 hsai->XferSize = Size; 01330 hsai->XferCount = Size; 01331 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01332 hsai->State = HAL_SAI_STATE_BUSY_RX; 01333 01334 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 01335 { 01336 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit; 01337 } 01338 else if (hsai->Init.DataSize <= SAI_DATASIZE_16) 01339 { 01340 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit; 01341 } 01342 else 01343 { 01344 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit; 01345 } 01346 01347 /* Enable TXE and OVRUDR interrupts */ 01348 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 01349 01350 /* Check if the SAI is already enabled */ 01351 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01352 { 01353 /* Enable SAI peripheral */ 01354 __HAL_SAI_ENABLE(hsai); 01355 } 01356 01357 /* Process Unlocked */ 01358 __HAL_UNLOCK(hsai); 01359 01360 return HAL_OK; 01361 } 01362 else 01363 { 01364 return HAL_BUSY; 01365 } 01366 } 01367 01368 /** 01369 * @brief Pause the audio stream playing from the Media. 01370 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01371 * the configuration information for SAI module. 01372 * @retval HAL status 01373 */ 01374 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai) 01375 { 01376 /* Process Locked */ 01377 __HAL_LOCK(hsai); 01378 01379 /* Pause the audio file playing by disabling the SAI DMA requests */ 01380 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 01381 01382 /* Process Unlocked */ 01383 __HAL_UNLOCK(hsai); 01384 01385 return HAL_OK; 01386 } 01387 01388 /** 01389 * @brief Resume the audio stream playing from the Media. 01390 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01391 * the configuration information for SAI module. 01392 * @retval HAL status 01393 */ 01394 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai) 01395 { 01396 /* Process Locked */ 01397 __HAL_LOCK(hsai); 01398 01399 /* Enable the SAI DMA requests */ 01400 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 01401 01402 /* If the SAI peripheral is still not enabled, enable it */ 01403 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01404 { 01405 /* Enable SAI peripheral */ 01406 __HAL_SAI_ENABLE(hsai); 01407 } 01408 01409 /* Process Unlocked */ 01410 __HAL_UNLOCK(hsai); 01411 01412 return HAL_OK; 01413 } 01414 01415 /** 01416 * @brief Stop the audio stream playing from the Media. 01417 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01418 * the configuration information for SAI module. 01419 * @retval HAL status 01420 */ 01421 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai) 01422 { 01423 HAL_StatusTypeDef status = HAL_OK; 01424 01425 /* Process Locked */ 01426 __HAL_LOCK(hsai); 01427 01428 /* Disable the SAI DMA request */ 01429 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 01430 01431 /* Abort the SAI Tx DMA Stream */ 01432 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL)) 01433 { 01434 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) 01435 { 01436 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */ 01437 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER) 01438 { 01439 status = HAL_ERROR; 01440 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01441 } 01442 } 01443 } 01444 01445 /* Abort the SAI Rx DMA Stream */ 01446 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL)) 01447 { 01448 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) 01449 { 01450 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */ 01451 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER) 01452 { 01453 status = HAL_ERROR; 01454 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01455 } 01456 } 01457 } 01458 01459 /* Disable SAI peripheral */ 01460 if (SAI_Disable(hsai) != HAL_OK) 01461 { 01462 status = HAL_ERROR; 01463 } 01464 01465 /* Flush the fifo */ 01466 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01467 01468 /* Set hsai state to ready */ 01469 hsai->State = HAL_SAI_STATE_READY; 01470 01471 /* Process Unlocked */ 01472 __HAL_UNLOCK(hsai); 01473 01474 return status; 01475 } 01476 01477 /** 01478 * @brief Abort the current transfer and disable the SAI. 01479 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01480 * the configuration information for SAI module. 01481 * @retval HAL status 01482 */ 01483 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai) 01484 { 01485 HAL_StatusTypeDef status = HAL_OK; 01486 01487 /* Process Locked */ 01488 __HAL_LOCK(hsai); 01489 01490 /* Check SAI DMA is enabled or not */ 01491 if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01492 { 01493 /* Disable the SAI DMA request */ 01494 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 01495 01496 /* Abort the SAI Tx DMA Stream */ 01497 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL)) 01498 { 01499 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) 01500 { 01501 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */ 01502 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER) 01503 { 01504 status = HAL_ERROR; 01505 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01506 } 01507 } 01508 } 01509 01510 /* Abort the SAI Rx DMA Stream */ 01511 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL)) 01512 { 01513 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) 01514 { 01515 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */ 01516 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER) 01517 { 01518 status = HAL_ERROR; 01519 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01520 } 01521 } 01522 } 01523 } 01524 01525 /* Disabled All interrupt and clear all the flag */ 01526 hsai->Instance->IMR = 0; 01527 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01528 01529 /* Disable SAI peripheral */ 01530 if (SAI_Disable(hsai) != HAL_OK) 01531 { 01532 status = HAL_ERROR; 01533 } 01534 01535 /* Flush the fifo */ 01536 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 01537 01538 /* Set hsai state to ready */ 01539 hsai->State = HAL_SAI_STATE_READY; 01540 01541 /* Process Unlocked */ 01542 __HAL_UNLOCK(hsai); 01543 01544 return status; 01545 } 01546 01547 /** 01548 * @brief Transmit an amount of data in non-blocking mode with DMA. 01549 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01550 * the configuration information for SAI module. 01551 * @param pData Pointer to data buffer 01552 * @param Size Amount of data to be sent 01553 * @retval HAL status 01554 */ 01555 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01556 { 01557 uint32_t tickstart = HAL_GetTick(); 01558 01559 if ((pData == NULL) || (Size == 0U)) 01560 { 01561 return HAL_ERROR; 01562 } 01563 01564 if (hsai->State == HAL_SAI_STATE_READY) 01565 { 01566 /* Process Locked */ 01567 __HAL_LOCK(hsai); 01568 01569 hsai->pBuffPtr = pData; 01570 hsai->XferSize = Size; 01571 hsai->XferCount = Size; 01572 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01573 hsai->State = HAL_SAI_STATE_BUSY_TX; 01574 01575 /* Set the SAI Tx DMA Half transfer complete callback */ 01576 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt; 01577 01578 /* Set the SAI TxDMA transfer complete callback */ 01579 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt; 01580 01581 /* Set the DMA error callback */ 01582 hsai->hdmatx->XferErrorCallback = SAI_DMAError; 01583 01584 /* Set the DMA Tx abort callback */ 01585 hsai->hdmatx->XferAbortCallback = NULL; 01586 01587 /* Enable the Tx DMA Stream */ 01588 if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK) 01589 { 01590 __HAL_UNLOCK(hsai); 01591 return HAL_ERROR; 01592 } 01593 01594 /* Enable the interrupts for error handling */ 01595 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 01596 01597 /* Enable SAI Tx DMA Request */ 01598 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 01599 01600 /* Wait untill FIFO is not empty */ 01601 while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY) 01602 { 01603 /* Check for the Timeout */ 01604 if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT) 01605 { 01606 /* Update error code */ 01607 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 01608 01609 /* Process Unlocked */ 01610 __HAL_UNLOCK(hsai); 01611 01612 return HAL_TIMEOUT; 01613 } 01614 } 01615 01616 /* Check if the SAI is already enabled */ 01617 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01618 { 01619 /* Enable SAI peripheral */ 01620 __HAL_SAI_ENABLE(hsai); 01621 } 01622 01623 /* Process Unlocked */ 01624 __HAL_UNLOCK(hsai); 01625 01626 return HAL_OK; 01627 } 01628 else 01629 { 01630 return HAL_BUSY; 01631 } 01632 } 01633 01634 /** 01635 * @brief Receive an amount of data in non-blocking mode with DMA. 01636 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01637 * the configuration information for SAI module. 01638 * @param pData Pointer to data buffer 01639 * @param Size Amount of data to be received 01640 * @retval HAL status 01641 */ 01642 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) 01643 { 01644 01645 if ((pData == NULL) || (Size == 0U)) 01646 { 01647 return HAL_ERROR; 01648 } 01649 01650 if (hsai->State == HAL_SAI_STATE_READY) 01651 { 01652 /* Process Locked */ 01653 __HAL_LOCK(hsai); 01654 01655 hsai->pBuffPtr = pData; 01656 hsai->XferSize = Size; 01657 hsai->XferCount = Size; 01658 hsai->ErrorCode = HAL_SAI_ERROR_NONE; 01659 hsai->State = HAL_SAI_STATE_BUSY_RX; 01660 01661 /* Set the SAI Rx DMA Half transfer complete callback */ 01662 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt; 01663 01664 /* Set the SAI Rx DMA transfer complete callback */ 01665 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt; 01666 01667 /* Set the DMA error callback */ 01668 hsai->hdmarx->XferErrorCallback = SAI_DMAError; 01669 01670 /* Set the DMA Rx abort callback */ 01671 hsai->hdmarx->XferAbortCallback = NULL; 01672 01673 /* Enable the Rx DMA Stream */ 01674 if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK) 01675 { 01676 __HAL_UNLOCK(hsai); 01677 return HAL_ERROR; 01678 } 01679 01680 /* Check if the SAI is already enabled */ 01681 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) 01682 { 01683 /* Enable SAI peripheral */ 01684 __HAL_SAI_ENABLE(hsai); 01685 } 01686 01687 /* Enable the interrupts for error handling */ 01688 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 01689 01690 /* Enable SAI Rx DMA Request */ 01691 hsai->Instance->CR1 |= SAI_xCR1_DMAEN; 01692 01693 /* Process Unlocked */ 01694 __HAL_UNLOCK(hsai); 01695 01696 return HAL_OK; 01697 } 01698 else 01699 { 01700 return HAL_BUSY; 01701 } 01702 } 01703 01704 /** 01705 * @brief Enable the Tx mute mode. 01706 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01707 * the configuration information for SAI module. 01708 * @param val value sent during the mute @ref SAI_Block_Mute_Value 01709 * @retval HAL status 01710 */ 01711 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val) 01712 { 01713 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val)); 01714 01715 if (hsai->State != HAL_SAI_STATE_RESET) 01716 { 01717 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); 01718 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val); 01719 return HAL_OK; 01720 } 01721 return HAL_ERROR; 01722 } 01723 01724 /** 01725 * @brief Disable the Tx mute mode. 01726 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01727 * the configuration information for SAI module. 01728 * @retval HAL status 01729 */ 01730 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai) 01731 { 01732 if (hsai->State != HAL_SAI_STATE_RESET) 01733 { 01734 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); 01735 return HAL_OK; 01736 } 01737 return HAL_ERROR; 01738 } 01739 01740 /** 01741 * @brief Enable the Rx mute detection. 01742 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01743 * the configuration information for SAI module. 01744 * @param callback function called when the mute is detected. 01745 * @param counter number a data before mute detection max 63. 01746 * @retval HAL status 01747 */ 01748 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter) 01749 { 01750 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter)); 01751 01752 if (hsai->State != HAL_SAI_STATE_RESET) 01753 { 01754 /* set the mute counter */ 01755 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT); 01756 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos)); 01757 hsai->mutecallback = callback; 01758 /* enable the IT interrupt */ 01759 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET); 01760 return HAL_OK; 01761 } 01762 return HAL_ERROR; 01763 } 01764 01765 /** 01766 * @brief Disable the Rx mute detection. 01767 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01768 * the configuration information for SAI module. 01769 * @retval HAL status 01770 */ 01771 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai) 01772 { 01773 if (hsai->State != HAL_SAI_STATE_RESET) 01774 { 01775 /* set the mutecallback to NULL */ 01776 hsai->mutecallback = NULL; 01777 /* enable the IT interrupt */ 01778 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET); 01779 return HAL_OK; 01780 } 01781 return HAL_ERROR; 01782 } 01783 01784 /** 01785 * @brief Handle SAI interrupt request. 01786 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 01787 * the configuration information for SAI module. 01788 * @retval None 01789 */ 01790 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai) 01791 { 01792 if (hsai->State != HAL_SAI_STATE_RESET) 01793 { 01794 uint32_t itflags = hsai->Instance->SR; 01795 uint32_t itsources = hsai->Instance->IMR; 01796 uint32_t cr1config = hsai->Instance->CR1; 01797 uint32_t tmperror; 01798 01799 /* SAI Fifo request interrupt occurred -----------------------------------*/ 01800 if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ)) 01801 { 01802 hsai->InterruptServiceRoutine(hsai); 01803 } 01804 /* SAI Overrun error interrupt occurred ----------------------------------*/ 01805 else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR)) 01806 { 01807 /* Clear the SAI Overrun flag */ 01808 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 01809 /* Get the SAI error code */ 01810 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR); 01811 /* Change the SAI error code */ 01812 hsai->ErrorCode |= tmperror; 01813 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ 01814 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 01815 hsai->ErrorCallback(hsai); 01816 #else 01817 HAL_SAI_ErrorCallback(hsai); 01818 #endif 01819 } 01820 /* SAI mutedet interrupt occurred ----------------------------------*/ 01821 else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET)) 01822 { 01823 /* Clear the SAI mutedet flag */ 01824 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET); 01825 /* call the call back function */ 01826 if (hsai->mutecallback != NULL) 01827 { 01828 /* inform the user that an RX mute event has been detected */ 01829 hsai->mutecallback(); 01830 } 01831 } 01832 /* SAI AFSDET interrupt occurred ----------------------------------*/ 01833 else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET)) 01834 { 01835 /* Change the SAI error code */ 01836 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET; 01837 01838 /* Check SAI DMA is enabled or not */ 01839 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01840 { 01841 /* Abort the SAI DMA Streams */ 01842 if (hsai->hdmatx != NULL) 01843 { 01844 /* Set the DMA Tx abort callback */ 01845 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01846 01847 /* Abort DMA in IT mode */ 01848 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK) 01849 { 01850 /* Update SAI error code */ 01851 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01852 01853 /* Call SAI error callback */ 01854 HAL_SAI_ErrorCallback(hsai); 01855 } 01856 } 01857 if (hsai->hdmarx != NULL) 01858 { 01859 /* Set the DMA Rx abort callback */ 01860 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01861 01862 /* Abort DMA in IT mode */ 01863 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK) 01864 { 01865 /* Update SAI error code */ 01866 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01867 01868 /* Call SAI error callback */ 01869 HAL_SAI_ErrorCallback(hsai); 01870 } 01871 } 01872 } 01873 else 01874 { 01875 /* Abort SAI */ 01876 if (HAL_SAI_Abort(hsai) != HAL_OK) 01877 { 01878 /* Nothing to do because HAL_SAI_ErrorCallback will be called later */ 01879 } 01880 01881 /* Set error callback */ 01882 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 01883 hsai->ErrorCallback(hsai); 01884 #else 01885 HAL_SAI_ErrorCallback(hsai); 01886 #endif 01887 } 01888 } 01889 /* SAI LFSDET interrupt occurred ----------------------------------*/ 01890 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET)) 01891 { 01892 /* Change the SAI error code */ 01893 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET; 01894 01895 /* Check SAI DMA is enabled or not */ 01896 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01897 { 01898 /* Abort the SAI DMA Streams */ 01899 if (hsai->hdmatx != NULL) 01900 { 01901 /* Set the DMA Tx abort callback */ 01902 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01903 01904 /* Abort DMA in IT mode */ 01905 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK) 01906 { 01907 /* Update SAI error code */ 01908 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01909 01910 /* Call SAI error callback */ 01911 HAL_SAI_ErrorCallback(hsai); 01912 } 01913 } 01914 if (hsai->hdmarx != NULL) 01915 { 01916 /* Set the DMA Rx abort callback */ 01917 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01918 01919 /* Abort DMA in IT mode */ 01920 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK) 01921 { 01922 /* Update SAI error code */ 01923 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01924 01925 /* Call SAI error callback */ 01926 HAL_SAI_ErrorCallback(hsai); 01927 } 01928 } 01929 } 01930 else 01931 { 01932 /* Abort SAI */ 01933 if (HAL_SAI_Abort(hsai) != HAL_OK) 01934 { 01935 /* Nothing to do because HAL_SAI_ErrorCallback will be called later */ 01936 } 01937 01938 /* Set error callback */ 01939 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 01940 hsai->ErrorCallback(hsai); 01941 #else 01942 HAL_SAI_ErrorCallback(hsai); 01943 #endif 01944 } 01945 } 01946 /* SAI WCKCFG interrupt occurred ----------------------------------*/ 01947 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG)) 01948 { 01949 /* Change the SAI error code */ 01950 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG; 01951 01952 /* Check SAI DMA is enabled or not */ 01953 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) 01954 { 01955 /* Abort the SAI DMA Streams */ 01956 if (hsai->hdmatx != NULL) 01957 { 01958 /* Set the DMA Tx abort callback */ 01959 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; 01960 01961 /* Abort DMA in IT mode */ 01962 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK) 01963 { 01964 /* Update SAI error code */ 01965 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01966 01967 /* Call SAI error callback */ 01968 HAL_SAI_ErrorCallback(hsai); 01969 } 01970 } 01971 if (hsai->hdmarx != NULL) 01972 { 01973 /* Set the DMA Rx abort callback */ 01974 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; 01975 01976 /* Abort DMA in IT mode */ 01977 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK) 01978 { 01979 /* Update SAI error code */ 01980 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 01981 01982 /* Call SAI error callback */ 01983 HAL_SAI_ErrorCallback(hsai); 01984 } 01985 } 01986 } 01987 else 01988 { 01989 /* If WCKCFG occurs, SAI audio block is automatically disabled */ 01990 /* Disable all interrupts and clear all flags */ 01991 hsai->Instance->IMR = 0U; 01992 hsai->Instance->CLRFR = 0xFFFFFFFFU; 01993 /* Set the SAI state to ready to be able to start again the process */ 01994 hsai->State = HAL_SAI_STATE_READY; 01995 01996 /* Initialize XferCount */ 01997 hsai->XferCount = 0U; 01998 01999 /* SAI error Callback */ 02000 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02001 hsai->ErrorCallback(hsai); 02002 #else 02003 HAL_SAI_ErrorCallback(hsai); 02004 #endif 02005 } 02006 } 02007 /* SAI CNRDY interrupt occurred ----------------------------------*/ 02008 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY)) 02009 { 02010 /* Clear the SAI CNRDY flag */ 02011 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY); 02012 /* Change the SAI error code */ 02013 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY; 02014 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ 02015 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02016 hsai->ErrorCallback(hsai); 02017 #else 02018 HAL_SAI_ErrorCallback(hsai); 02019 #endif 02020 } 02021 else 02022 { 02023 /* Nothing to do */ 02024 } 02025 } 02026 } 02027 02028 /** 02029 * @brief Tx Transfer completed callback. 02030 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02031 * the configuration information for SAI module. 02032 * @retval None 02033 */ 02034 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 02035 { 02036 /* Prevent unused argument(s) compilation warning */ 02037 UNUSED(hsai); 02038 02039 /* NOTE : This function should not be modified, when the callback is needed, 02040 the HAL_SAI_TxCpltCallback could be implemented in the user file 02041 */ 02042 } 02043 02044 /** 02045 * @brief Tx Transfer Half completed callback. 02046 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02047 * the configuration information for SAI module. 02048 * @retval None 02049 */ 02050 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 02051 { 02052 /* Prevent unused argument(s) compilation warning */ 02053 UNUSED(hsai); 02054 02055 /* NOTE : This function should not be modified, when the callback is needed, 02056 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file 02057 */ 02058 } 02059 02060 /** 02061 * @brief Rx Transfer completed callback. 02062 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02063 * the configuration information for SAI module. 02064 * @retval None 02065 */ 02066 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) 02067 { 02068 /* Prevent unused argument(s) compilation warning */ 02069 UNUSED(hsai); 02070 02071 /* NOTE : This function should not be modified, when the callback is needed, 02072 the HAL_SAI_RxCpltCallback could be implemented in the user file 02073 */ 02074 } 02075 02076 /** 02077 * @brief Rx Transfer half completed callback. 02078 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02079 * the configuration information for SAI module. 02080 * @retval None 02081 */ 02082 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) 02083 { 02084 /* Prevent unused argument(s) compilation warning */ 02085 UNUSED(hsai); 02086 02087 /* NOTE : This function should not be modified, when the callback is needed, 02088 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file 02089 */ 02090 } 02091 02092 /** 02093 * @brief SAI error callback. 02094 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02095 * the configuration information for SAI module. 02096 * @retval None 02097 */ 02098 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 02099 { 02100 /* Prevent unused argument(s) compilation warning */ 02101 UNUSED(hsai); 02102 02103 /* NOTE : This function should not be modified, when the callback is needed, 02104 the HAL_SAI_ErrorCallback could be implemented in the user file 02105 */ 02106 } 02107 02108 /** 02109 * @} 02110 */ 02111 02112 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions 02113 * @brief Peripheral State functions 02114 * 02115 @verbatim 02116 =============================================================================== 02117 ##### Peripheral State and Errors functions ##### 02118 =============================================================================== 02119 [..] 02120 This subsection permits to get in run-time the status of the peripheral 02121 and the data flow. 02122 02123 @endverbatim 02124 * @{ 02125 */ 02126 02127 /** 02128 * @brief Return the SAI handle state. 02129 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02130 * the configuration information for SAI module. 02131 * @retval HAL state 02132 */ 02133 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai) 02134 { 02135 return hsai->State; 02136 } 02137 02138 /** 02139 * @brief Return the SAI error code. 02140 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02141 * the configuration information for the specified SAI Block. 02142 * @retval SAI Error Code 02143 */ 02144 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai) 02145 { 02146 return hsai->ErrorCode; 02147 } 02148 02149 /** 02150 * @} 02151 */ 02152 02153 /** 02154 * @} 02155 */ 02156 02157 /** @addtogroup SAI_Private_Functions 02158 * @brief Private functions 02159 * @{ 02160 */ 02161 02162 /** 02163 * @brief Initialize the SAI I2S protocol according to the specified parameters 02164 * in the SAI_InitTypeDef and create the associated handle. 02165 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02166 * the configuration information for SAI module. 02167 * @param protocol one of the supported protocol. 02168 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize. 02169 * @param nbslot number of slot minimum value is 2 and max is 16. 02170 * the value must be a multiple of 2. 02171 * @retval HAL status 02172 */ 02173 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 02174 { 02175 HAL_StatusTypeDef status = HAL_OK; 02176 02177 hsai->Init.Protocol = SAI_FREE_PROTOCOL; 02178 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; 02179 /* Compute ClockStrobing according AudioMode */ 02180 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 02181 { 02182 /* Transmit */ 02183 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 02184 } 02185 else 02186 { 02187 /* Receive */ 02188 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 02189 } 02190 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 02191 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; 02192 hsai->SlotInit.FirstBitOffset = 0; 02193 hsai->SlotInit.SlotNumber = nbslot; 02194 02195 /* in IS2 the number of slot must be even */ 02196 if ((nbslot & 0x1U) != 0U) 02197 { 02198 return HAL_ERROR; 02199 } 02200 02201 switch (protocol) 02202 { 02203 case SAI_I2S_STANDARD : 02204 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 02205 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 02206 break; 02207 case SAI_I2S_MSBJUSTIFIED : 02208 case SAI_I2S_LSBJUSTIFIED : 02209 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; 02210 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT; 02211 break; 02212 default : 02213 status = HAL_ERROR; 02214 break; 02215 } 02216 02217 /* Frame definition */ 02218 switch (datasize) 02219 { 02220 case SAI_PROTOCOL_DATASIZE_16BIT: 02221 hsai->Init.DataSize = SAI_DATASIZE_16; 02222 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U); 02223 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U); 02224 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; 02225 break; 02226 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : 02227 hsai->Init.DataSize = SAI_DATASIZE_16; 02228 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); 02229 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); 02230 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02231 break; 02232 case SAI_PROTOCOL_DATASIZE_24BIT: 02233 hsai->Init.DataSize = SAI_DATASIZE_24; 02234 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); 02235 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); 02236 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02237 break; 02238 case SAI_PROTOCOL_DATASIZE_32BIT: 02239 hsai->Init.DataSize = SAI_DATASIZE_32; 02240 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); 02241 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); 02242 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02243 break; 02244 default : 02245 status = HAL_ERROR; 02246 break; 02247 } 02248 if (protocol == SAI_I2S_LSBJUSTIFIED) 02249 { 02250 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED) 02251 { 02252 hsai->SlotInit.FirstBitOffset = 16; 02253 } 02254 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT) 02255 { 02256 hsai->SlotInit.FirstBitOffset = 8; 02257 } 02258 } 02259 return status; 02260 } 02261 02262 /** 02263 * @brief Initialize the SAI PCM protocol according to the specified parameters 02264 * in the SAI_InitTypeDef and create the associated handle. 02265 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02266 * the configuration information for SAI module. 02267 * @param protocol one of the supported protocol 02268 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize 02269 * @param nbslot number of slot minimum value is 1 and the max is 16. 02270 * @retval HAL status 02271 */ 02272 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) 02273 { 02274 HAL_StatusTypeDef status = HAL_OK; 02275 02276 hsai->Init.Protocol = SAI_FREE_PROTOCOL; 02277 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; 02278 /* Compute ClockStrobing according AudioMode */ 02279 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 02280 { 02281 /* Transmit */ 02282 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 02283 } 02284 else 02285 { 02286 /* Receive */ 02287 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; 02288 } 02289 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME; 02290 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; 02291 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 02292 hsai->SlotInit.FirstBitOffset = 0; 02293 hsai->SlotInit.SlotNumber = nbslot; 02294 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; 02295 02296 switch (protocol) 02297 { 02298 case SAI_PCM_SHORT : 02299 hsai->FrameInit.ActiveFrameLength = 1; 02300 break; 02301 case SAI_PCM_LONG : 02302 hsai->FrameInit.ActiveFrameLength = 13; 02303 break; 02304 default : 02305 status = HAL_ERROR; 02306 break; 02307 } 02308 02309 switch (datasize) 02310 { 02311 case SAI_PROTOCOL_DATASIZE_16BIT: 02312 hsai->Init.DataSize = SAI_DATASIZE_16; 02313 hsai->FrameInit.FrameLength = 16U * nbslot; 02314 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; 02315 break; 02316 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : 02317 hsai->Init.DataSize = SAI_DATASIZE_16; 02318 hsai->FrameInit.FrameLength = 32U * nbslot; 02319 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02320 break; 02321 case SAI_PROTOCOL_DATASIZE_24BIT : 02322 hsai->Init.DataSize = SAI_DATASIZE_24; 02323 hsai->FrameInit.FrameLength = 32U * nbslot; 02324 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02325 break; 02326 case SAI_PROTOCOL_DATASIZE_32BIT: 02327 hsai->Init.DataSize = SAI_DATASIZE_32; 02328 hsai->FrameInit.FrameLength = 32U * nbslot; 02329 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; 02330 break; 02331 default : 02332 status = HAL_ERROR; 02333 break; 02334 } 02335 02336 return status; 02337 } 02338 02339 /** 02340 * @brief Fill the fifo. 02341 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02342 * the configuration information for SAI module. 02343 * @retval None 02344 */ 02345 static void SAI_FillFifo(SAI_HandleTypeDef *hsai) 02346 { 02347 uint32_t temp; 02348 02349 /* fill the fifo with data before to enabled the SAI */ 02350 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U)) 02351 { 02352 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) 02353 { 02354 hsai->Instance->DR = *hsai->pBuffPtr; 02355 hsai->pBuffPtr++; 02356 } 02357 else if (hsai->Init.DataSize <= SAI_DATASIZE_16) 02358 { 02359 temp = (uint32_t)(*hsai->pBuffPtr); 02360 hsai->pBuffPtr++; 02361 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 02362 hsai->pBuffPtr++; 02363 hsai->Instance->DR = temp; 02364 } 02365 else 02366 { 02367 temp = (uint32_t)(*hsai->pBuffPtr); 02368 hsai->pBuffPtr++; 02369 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 02370 hsai->pBuffPtr++; 02371 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16); 02372 hsai->pBuffPtr++; 02373 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24); 02374 hsai->pBuffPtr++; 02375 hsai->Instance->DR = temp; 02376 } 02377 hsai->XferCount--; 02378 } 02379 } 02380 02381 /** 02382 * @brief Return the interrupt flag to set according the SAI setup. 02383 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02384 * the configuration information for SAI module. 02385 * @param mode SAI_MODE_DMA or SAI_MODE_IT 02386 * @retval the list of the IT flag to enable 02387 */ 02388 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode) 02389 { 02390 uint32_t tmpIT = SAI_IT_OVRUDR; 02391 02392 if (mode == SAI_MODE_IT) 02393 { 02394 tmpIT |= SAI_IT_FREQ; 02395 } 02396 02397 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) && 02398 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX))) 02399 { 02400 tmpIT |= SAI_IT_CNRDY; 02401 } 02402 02403 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) 02404 { 02405 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET; 02406 } 02407 else 02408 { 02409 /* hsai has been configured in master mode */ 02410 tmpIT |= SAI_IT_WCKCFG; 02411 } 02412 return tmpIT; 02413 } 02414 02415 /** 02416 * @brief Disable the SAI and wait for the disabling. 02417 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02418 * the configuration information for SAI module. 02419 * @retval None 02420 */ 02421 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai) 02422 { 02423 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U); 02424 HAL_StatusTypeDef status = HAL_OK; 02425 02426 /* Disable the SAI instance */ 02427 __HAL_SAI_DISABLE(hsai); 02428 02429 do 02430 { 02431 /* Check for the Timeout */ 02432 if (count == 0U) 02433 { 02434 /* Update error code */ 02435 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; 02436 status = HAL_TIMEOUT; 02437 break; 02438 } 02439 count--; 02440 } 02441 while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U); 02442 02443 return status; 02444 } 02445 02446 /** 02447 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer. 02448 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02449 * the configuration information for SAI module. 02450 * @retval None 02451 */ 02452 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai) 02453 { 02454 if (hsai->XferCount == 0U) 02455 { 02456 /* Handle the end of the transmission */ 02457 /* Disable FREQ and OVRUDR interrupts */ 02458 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02459 hsai->State = HAL_SAI_STATE_READY; 02460 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02461 hsai->TxCpltCallback(hsai); 02462 #else 02463 HAL_SAI_TxCpltCallback(hsai); 02464 #endif 02465 } 02466 else 02467 { 02468 /* Write data on DR register */ 02469 hsai->Instance->DR = *hsai->pBuffPtr; 02470 hsai->pBuffPtr++; 02471 hsai->XferCount--; 02472 } 02473 } 02474 02475 /** 02476 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer. 02477 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02478 * the configuration information for SAI module. 02479 * @retval None 02480 */ 02481 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai) 02482 { 02483 if (hsai->XferCount == 0U) 02484 { 02485 /* Handle the end of the transmission */ 02486 /* Disable FREQ and OVRUDR interrupts */ 02487 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02488 hsai->State = HAL_SAI_STATE_READY; 02489 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02490 hsai->TxCpltCallback(hsai); 02491 #else 02492 HAL_SAI_TxCpltCallback(hsai); 02493 #endif 02494 } 02495 else 02496 { 02497 /* Write data on DR register */ 02498 uint32_t temp; 02499 temp = (uint32_t)(*hsai->pBuffPtr); 02500 hsai->pBuffPtr++; 02501 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 02502 hsai->pBuffPtr++; 02503 hsai->Instance->DR = temp; 02504 hsai->XferCount--; 02505 } 02506 } 02507 02508 /** 02509 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer. 02510 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02511 * the configuration information for SAI module. 02512 * @retval None 02513 */ 02514 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai) 02515 { 02516 if (hsai->XferCount == 0U) 02517 { 02518 /* Handle the end of the transmission */ 02519 /* Disable FREQ and OVRUDR interrupts */ 02520 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02521 hsai->State = HAL_SAI_STATE_READY; 02522 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02523 hsai->TxCpltCallback(hsai); 02524 #else 02525 HAL_SAI_TxCpltCallback(hsai); 02526 #endif 02527 } 02528 else 02529 { 02530 /* Write data on DR register */ 02531 uint32_t temp; 02532 temp = (uint32_t)(*hsai->pBuffPtr); 02533 hsai->pBuffPtr++; 02534 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8); 02535 hsai->pBuffPtr++; 02536 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16); 02537 hsai->pBuffPtr++; 02538 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24); 02539 hsai->pBuffPtr++; 02540 hsai->Instance->DR = temp; 02541 hsai->XferCount--; 02542 } 02543 } 02544 02545 /** 02546 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer. 02547 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02548 * the configuration information for SAI module. 02549 * @retval None 02550 */ 02551 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai) 02552 { 02553 /* Receive data */ 02554 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR; 02555 hsai->pBuffPtr++; 02556 hsai->XferCount--; 02557 02558 /* Check end of the transfer */ 02559 if (hsai->XferCount == 0U) 02560 { 02561 /* Disable TXE and OVRUDR interrupts */ 02562 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02563 02564 /* Clear the SAI Overrun flag */ 02565 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 02566 02567 hsai->State = HAL_SAI_STATE_READY; 02568 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02569 hsai->RxCpltCallback(hsai); 02570 #else 02571 HAL_SAI_RxCpltCallback(hsai); 02572 #endif 02573 } 02574 } 02575 02576 /** 02577 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer. 02578 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02579 * the configuration information for SAI module. 02580 * @retval None 02581 */ 02582 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai) 02583 { 02584 uint32_t temp; 02585 02586 /* Receive data */ 02587 temp = hsai->Instance->DR; 02588 *hsai->pBuffPtr = (uint8_t)temp; 02589 hsai->pBuffPtr++; 02590 *hsai->pBuffPtr = (uint8_t)(temp >> 8); 02591 hsai->pBuffPtr++; 02592 hsai->XferCount--; 02593 02594 /* Check end of the transfer */ 02595 if (hsai->XferCount == 0U) 02596 { 02597 /* Disable TXE and OVRUDR interrupts */ 02598 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02599 02600 /* Clear the SAI Overrun flag */ 02601 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 02602 02603 hsai->State = HAL_SAI_STATE_READY; 02604 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02605 hsai->RxCpltCallback(hsai); 02606 #else 02607 HAL_SAI_RxCpltCallback(hsai); 02608 #endif 02609 } 02610 } 02611 02612 /** 02613 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer. 02614 * @param hsai pointer to a SAI_HandleTypeDef structure that contains 02615 * the configuration information for SAI module. 02616 * @retval None 02617 */ 02618 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai) 02619 { 02620 uint32_t temp; 02621 02622 /* Receive data */ 02623 temp = hsai->Instance->DR; 02624 *hsai->pBuffPtr = (uint8_t)temp; 02625 hsai->pBuffPtr++; 02626 *hsai->pBuffPtr = (uint8_t)(temp >> 8); 02627 hsai->pBuffPtr++; 02628 *hsai->pBuffPtr = (uint8_t)(temp >> 16); 02629 hsai->pBuffPtr++; 02630 *hsai->pBuffPtr = (uint8_t)(temp >> 24); 02631 hsai->pBuffPtr++; 02632 hsai->XferCount--; 02633 02634 /* Check end of the transfer */ 02635 if (hsai->XferCount == 0U) 02636 { 02637 /* Disable TXE and OVRUDR interrupts */ 02638 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); 02639 02640 /* Clear the SAI Overrun flag */ 02641 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); 02642 02643 hsai->State = HAL_SAI_STATE_READY; 02644 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02645 hsai->RxCpltCallback(hsai); 02646 #else 02647 HAL_SAI_RxCpltCallback(hsai); 02648 #endif 02649 } 02650 } 02651 02652 /** 02653 * @brief DMA SAI transmit process complete callback. 02654 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02655 * the configuration information for the specified DMA module. 02656 * @retval None 02657 */ 02658 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma) 02659 { 02660 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02661 02662 if (hdma->Init.Mode != DMA_CIRCULAR) 02663 { 02664 hsai->XferCount = 0; 02665 02666 /* Disable SAI Tx DMA Request */ 02667 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); 02668 02669 /* Stop the interrupts error handling */ 02670 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 02671 02672 hsai->State = HAL_SAI_STATE_READY; 02673 } 02674 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02675 hsai->TxCpltCallback(hsai); 02676 #else 02677 HAL_SAI_TxCpltCallback(hsai); 02678 #endif 02679 } 02680 02681 /** 02682 * @brief DMA SAI transmit process half complete callback. 02683 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02684 * the configuration information for the specified DMA module. 02685 * @retval None 02686 */ 02687 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) 02688 { 02689 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02690 02691 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02692 hsai->TxHalfCpltCallback(hsai); 02693 #else 02694 HAL_SAI_TxHalfCpltCallback(hsai); 02695 #endif 02696 } 02697 02698 /** 02699 * @brief DMA SAI receive process complete callback. 02700 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02701 * the configuration information for the specified DMA module. 02702 * @retval None 02703 */ 02704 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma) 02705 { 02706 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02707 02708 if (hdma->Init.Mode != DMA_CIRCULAR) 02709 { 02710 /* Disable Rx DMA Request */ 02711 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); 02712 hsai->XferCount = 0; 02713 02714 /* Stop the interrupts error handling */ 02715 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); 02716 02717 hsai->State = HAL_SAI_STATE_READY; 02718 } 02719 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02720 hsai->RxCpltCallback(hsai); 02721 #else 02722 HAL_SAI_RxCpltCallback(hsai); 02723 #endif 02724 } 02725 02726 /** 02727 * @brief DMA SAI receive process half complete callback 02728 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02729 * the configuration information for the specified DMA module. 02730 * @retval None 02731 */ 02732 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) 02733 { 02734 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02735 02736 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02737 hsai->RxHalfCpltCallback(hsai); 02738 #else 02739 HAL_SAI_RxHalfCpltCallback(hsai); 02740 #endif 02741 } 02742 02743 /** 02744 * @brief DMA SAI communication error callback. 02745 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02746 * the configuration information for the specified DMA module. 02747 * @retval None 02748 */ 02749 static void SAI_DMAError(DMA_HandleTypeDef *hdma) 02750 { 02751 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02752 02753 /* Set SAI error code */ 02754 hsai->ErrorCode |= HAL_SAI_ERROR_DMA; 02755 02756 /* Disable the SAI DMA request */ 02757 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 02758 02759 /* Disable SAI peripheral */ 02760 if (SAI_Disable(hsai) != HAL_OK) 02761 { 02762 /* Nothing to do because state will be updated and HAL_SAI_ErrorCallback will be called later */ 02763 } 02764 02765 /* Set the SAI state ready to be able to start again the process */ 02766 hsai->State = HAL_SAI_STATE_READY; 02767 02768 /* Initialize XferCount */ 02769 hsai->XferCount = 0U; 02770 02771 /* SAI error Callback */ 02772 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02773 hsai->ErrorCallback(hsai); 02774 #else 02775 HAL_SAI_ErrorCallback(hsai); 02776 #endif 02777 } 02778 02779 /** 02780 * @brief DMA SAI Abort callback. 02781 * @param hdma pointer to a DMA_HandleTypeDef structure that contains 02782 * the configuration information for the specified DMA module. 02783 * @retval None 02784 */ 02785 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma) 02786 { 02787 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 02788 02789 /* Disable DMA request */ 02790 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; 02791 02792 /* Disable all interrupts and clear all flags */ 02793 hsai->Instance->IMR = 0U; 02794 hsai->Instance->CLRFR = 0xFFFFFFFFU; 02795 02796 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG) 02797 { 02798 /* Disable SAI peripheral */ 02799 if (SAI_Disable(hsai) != HAL_OK) 02800 { 02801 /* Nothing to do because state will be updated and HAL_SAI_ErrorCallback will be called later */ 02802 } 02803 02804 /* Flush the fifo */ 02805 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); 02806 } 02807 /* Set the SAI state to ready to be able to start again the process */ 02808 hsai->State = HAL_SAI_STATE_READY; 02809 02810 /* Initialize XferCount */ 02811 hsai->XferCount = 0U; 02812 02813 /* SAI error Callback */ 02814 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) 02815 hsai->ErrorCallback(hsai); 02816 #else 02817 HAL_SAI_ErrorCallback(hsai); 02818 #endif 02819 } 02820 02821 /** 02822 * @} 02823 */ 02824 02825 #endif /* HAL_SAI_MODULE_ENABLED */ 02826 /** 02827 * @} 02828 */ 02829 02830 /** 02831 * @} 02832 */ 02833 02834 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/