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