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