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