Updated and Validated
[betaflight.git] / lib / main / STM32F7 / Drivers / STM32F7xx_HAL_Driver / Src / stm32f7xx_hal_sai.c
blob3c2cddee7a053284664f41bfee133d08c06c9187
1 /**
2 ******************************************************************************
3 * @file stm32f7xx_hal_sai.c
4 * @author MCD Application Team
5 * @brief SAI HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the Serial Audio Interface (SAI) peripheral:
8 * + Initialization/de-initialization functions
9 * + I/O operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
13 @verbatim
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
18 [..]
19 The SAI HAL driver can be used as follows:
21 (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
22 (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
23 (##) Enable the SAI interface clock.
24 (##) SAI pins configuration:
25 (+++) Enable the clock for the SAI GPIOs.
26 (+++) Configure these SAI pins as alternate function pull-up.
27 (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
28 and HAL_SAI_Receive_IT() APIs):
29 (+++) Configure the SAI interrupt priority.
30 (+++) Enable the NVIC SAI IRQ handle.
32 (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
33 and HAL_SAI_Receive_DMA() APIs):
34 (+++) Declare a DMA handle structure for the Tx/Rx stream.
35 (+++) Enable the DMAx interface clock.
36 (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
37 (+++) Configure the DMA Tx/Rx Stream.
38 (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
39 (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
40 DMA Tx/Rx Stream.
42 (#) The initialization can be done by two ways
43 (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
44 (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
46 [..]
47 (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
48 will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
49 inside the transmit and receive process.
50 [..]
51 (@) Make sure that either:
52 (+@) I2S PLL is configured or
53 (+@) SAI PLL is configured or
54 (+@) External clock source is configured after setting correctly
55 the define constant EXTERNAL_CLOCK_VALUE in the stm32f7xx_hal_conf.h file.
56 [..]
57 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
58 for the external slaves even if there is no data in the FIFO, However FS signal
59 generation is conditioned by the presence of data in the FIFO.
61 [..]
62 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
63 and FS signal for the external slaves.
65 [..]
66 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
67 (+@) First bit Offset <= (SLOT size - Data size)
68 (+@) Data size <= SLOT size
69 (+@) Number of SLOT x SLOT size = Frame length
70 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
72 [..]
73 Three operation modes are available within this driver :
75 *** Polling mode IO operation ***
76 =================================
77 [..]
78 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
79 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
81 *** Interrupt mode IO operation ***
82 ===================================
83 [..]
84 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
85 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
86 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
87 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
88 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
89 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
90 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
91 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
93 *** DMA mode IO operation ***
94 =============================
95 [..]
96 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
97 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
98 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
99 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
100 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
101 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
102 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
103 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
104 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
105 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
106 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
108 *** SAI HAL driver additional function list ***
109 ===============================================
110 [..]
111 Below the list the others API available SAI HAL driver :
113 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
114 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
115 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
116 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
117 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
118 (+) HAL_SAI_Abort(): Abort the current transfer
120 *** SAI HAL driver macros list ***
121 ==================================
122 [..]
123 Below the list of most used macros in SAI HAL driver :
125 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
126 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
127 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
128 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
129 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
130 enabled or disabled
131 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
133 *** Callback registration ***
134 =============================
136 The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
137 allows the user to configure dynamically the driver callbacks.
138 Use functions @ref HAL_SAI_RegisterCallback() to register a user callback.
140 Function @ref HAL_SAI_RegisterCallback() allows to register following callbacks:
141 (+) RxCpltCallback : SAI receive complete.
142 (+) RxHalfCpltCallback : SAI receive half complete.
143 (+) TxCpltCallback : SAI transmit complete.
144 (+) TxHalfCpltCallback : SAI transmit half complete.
145 (+) ErrorCallback : SAI error.
146 (+) MspInitCallback : SAI MspInit.
147 (+) MspDeInitCallback : SAI MspDeInit.
148 This function takes as parameters the HAL peripheral handle, the callback ID
149 and a pointer to the user callback function.
151 Use function @ref HAL_SAI_UnRegisterCallback() to reset a callback to the default
152 weak (surcharged) function.
153 @ref HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
154 and the callback ID.
155 This function allows to reset following callbacks:
156 (+) RxCpltCallback : SAI receive complete.
157 (+) RxHalfCpltCallback : SAI receive half complete.
158 (+) TxCpltCallback : SAI transmit complete.
159 (+) TxHalfCpltCallback : SAI transmit half complete.
160 (+) ErrorCallback : SAI error.
161 (+) MspInitCallback : SAI MspInit.
162 (+) MspDeInitCallback : SAI MspDeInit.
164 By default, after the @ref HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
165 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
166 examples @ref HAL_SAI_RxCpltCallback(), @ref HAL_SAI_ErrorCallback().
167 Exception done for MspInit and MspDeInit callbacks that are respectively
168 reset to the legacy weak (surcharged) functions in the @ref HAL_SAI_Init
169 and @ref HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
170 If not, MspInit or MspDeInit are not null, the @ref HAL_SAI_Init and @ref HAL_SAI_DeInit
171 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
173 Callbacks can be registered/unregistered in READY state only.
174 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
175 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
176 during the Init/DeInit.
177 In that case first register the MspInit/MspDeInit user callbacks
178 using @ref HAL_SAI_RegisterCallback before calling @ref HAL_SAI_DeInit
179 or @ref HAL_SAI_Init function.
181 When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
182 not defined, the callback registering feature is not available
183 and weak (surcharged) callbacks are used.
185 @endverbatim
186 ******************************************************************************
187 * @attention
189 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
190 * All rights reserved.</center></h2>
192 * This software component is licensed by ST under BSD 3-Clause license,
193 * the "License"; You may not use this file except in compliance with the
194 * License. You may obtain a copy of the License at:
195 * opensource.org/licenses/BSD-3-Clause
197 ******************************************************************************
200 /* Includes ------------------------------------------------------------------*/
201 #include "stm32f7xx_hal.h"
203 /** @addtogroup STM32F7xx_HAL_Driver
204 * @{
207 /** @defgroup SAI SAI
208 * @brief SAI HAL module driver
209 * @{
212 #ifdef HAL_SAI_MODULE_ENABLED
214 /* Private typedef -----------------------------------------------------------*/
215 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
216 * @{
218 typedef enum {
219 SAI_MODE_DMA,
220 SAI_MODE_IT
221 }SAI_ModeTypedef;
223 * @}
226 /* Private define ------------------------------------------------------------*/
228 /** @defgroup SAI_Private_Constants SAI Private Constants
229 * @{
231 #define SAI_FIFO_SIZE 8
232 #define SAI_DEFAULT_TIMEOUT 4 /* 4ms */
234 * @}
237 /* Private macro -------------------------------------------------------------*/
238 /* Private variables ---------------------------------------------------------*/
239 /* Private function prototypes -----------------------------------------------*/
241 /** @defgroup SAI_Private_Functions SAI Private Functions
242 * @{
244 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
245 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
246 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
247 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
249 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
250 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
251 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
252 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
253 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
254 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
255 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
257 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
258 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
259 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
260 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
261 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
262 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
264 * @}
267 /* Exported functions ---------------------------------------------------------*/
269 /** @defgroup SAI_Exported_Functions SAI Exported Functions
270 * @{
273 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
274 * @brief Initialization and Configuration functions
276 @verbatim
277 ===============================================================================
278 ##### Initialization and de-initialization functions #####
279 ===============================================================================
280 [..] This subsection provides a set of functions allowing to initialize and
281 de-initialize the SAIx peripheral:
283 (+) User must implement HAL_SAI_MspInit() function in which he configures
284 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
286 (+) Call the function HAL_SAI_Init() to configure the selected device with
287 the selected configuration:
288 (++) Mode (Master/slave TX/RX)
289 (++) Protocol
290 (++) Data Size
291 (++) MCLK Output
292 (++) Audio frequency
293 (++) FIFO Threshold
294 (++) Frame Config
295 (++) Slot Config
297 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
298 of the selected SAI peripheral.
300 @endverbatim
301 * @{
305 * @brief Initialize the structure FrameInit, SlotInit and the low part of
306 * Init according to the specified parameters and call the function
307 * HAL_SAI_Init to initialize the SAI block.
308 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
309 * the configuration information for SAI module.
310 * @param protocol one of the supported protocol @ref SAI_Protocol
311 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
312 * the configuration information for SAI module.
313 * @param nbslot Number of slot.
314 * @retval HAL status
316 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
318 HAL_StatusTypeDef status = HAL_OK;
320 /* Check the parameters */
321 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
322 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
324 switch(protocol)
326 case SAI_I2S_STANDARD :
327 case SAI_I2S_MSBJUSTIFIED :
328 case SAI_I2S_LSBJUSTIFIED :
329 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
330 break;
331 case SAI_PCM_LONG :
332 case SAI_PCM_SHORT :
333 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
334 break;
335 default :
336 status = HAL_ERROR;
337 break;
340 if(status == HAL_OK)
342 status = HAL_SAI_Init(hsai);
345 return status;
349 * @brief Initialize the SAI according to the specified parameters.
350 * in the SAI_InitTypeDef structure and initialize the associated handle.
351 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
352 * the configuration information for SAI module.
353 * @retval HAL status
355 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
357 uint32_t tmpregisterGCR = 0;
358 uint32_t ckstr_bits = 0;
359 uint32_t syncen_bits = 0;
361 /* Check the SAI handle allocation */
362 if(hsai == NULL)
364 return HAL_ERROR;
367 /* check the instance */
368 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
370 /* Check the SAI Block parameters */
371 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
372 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
373 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
374 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
375 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
376 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
377 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
378 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
379 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
380 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
381 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
382 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
383 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
384 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
386 /* Check the SAI Block Frame parameters */
387 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
388 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
389 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
390 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
391 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
393 /* Check the SAI Block Slot parameters */
394 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
395 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
396 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
397 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
399 if(hsai->State == HAL_SAI_STATE_RESET)
401 /* Allocate lock resource and initialize it */
402 hsai->Lock = HAL_UNLOCKED;
404 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
405 /* Reset callback pointers to the weak predefined callbacks */
406 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
407 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
408 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
409 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
410 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
412 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
413 if (hsai->MspInitCallback == NULL)
415 hsai->MspInitCallback = HAL_SAI_MspInit;
417 hsai->MspInitCallback(hsai);
418 #else
419 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
420 HAL_SAI_MspInit(hsai);
421 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
424 hsai->State = HAL_SAI_STATE_BUSY;
426 /* Disable the selected SAI peripheral */
427 SAI_Disable(hsai);
429 /* SAI Block Synchro Configuration -----------------------------------------*/
430 /* This setting must be done with both audio block (A & B) disabled */
431 switch(hsai->Init.SynchroExt)
433 case SAI_SYNCEXT_DISABLE :
434 tmpregisterGCR = 0;
435 break;
436 case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
437 tmpregisterGCR = SAI_GCR_SYNCOUT_0;
438 break;
439 case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
440 tmpregisterGCR = SAI_GCR_SYNCOUT_1;
441 break;
442 default:
443 break;
446 switch(hsai->Init.Synchro)
448 case SAI_ASYNCHRONOUS :
450 syncen_bits = 0;
452 break;
453 case SAI_SYNCHRONOUS :
455 syncen_bits = SAI_xCR1_SYNCEN_0;
457 break;
458 case SAI_SYNCHRONOUS_EXT_SAI1 :
460 syncen_bits = SAI_xCR1_SYNCEN_1;
462 break;
463 case SAI_SYNCHRONOUS_EXT_SAI2 :
465 syncen_bits = SAI_xCR1_SYNCEN_1;
466 tmpregisterGCR |= SAI_GCR_SYNCIN_0;
468 break;
469 default:
470 break;
473 if((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
475 SAI1->GCR = tmpregisterGCR;
477 else
479 SAI2->GCR = tmpregisterGCR;
482 if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
484 uint32_t freq = 0;
485 uint32_t tmpval;
487 if((hsai->Instance == SAI1_Block_A ) || (hsai->Instance == SAI1_Block_B ))
489 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
491 if((hsai->Instance == SAI2_Block_A ) || (hsai->Instance == SAI2_Block_B ))
493 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
496 /* Configure Master Clock using the following formula :
497 MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
498 FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
499 MCKDIV[3:0] = SAI_CK_x / FS * 512 */
500 /* (freq x 10) to keep Significant digits */
501 tmpval = (freq * 10) / (hsai->Init.AudioFrequency * 2 * 256);
502 hsai->Init.Mckdiv = tmpval / 10;
504 /* Round result to the nearest integer */
505 if((tmpval % 10) > 8)
507 hsai->Init.Mckdiv+= 1;
511 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
512 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
513 { /* Transmit */
514 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0 : SAI_xCR1_CKSTR;
516 else
517 { /* Receive */
518 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0;
521 /* SAI Block Configuration -------------------------------------------------*/
522 /* SAI CR1 Configuration */
523 hsai->Instance->CR1&=~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
524 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\
525 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
526 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
528 hsai->Instance->CR1|=(hsai->Init.AudioMode | hsai->Init.Protocol | \
529 hsai->Init.DataSize | hsai->Init.FirstBit | \
530 ckstr_bits | syncen_bits | \
531 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
532 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20));
534 /* SAI CR2 Configuration */
535 hsai->Instance->CR2&= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
536 hsai->Instance->CR2|= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
538 /* SAI Frame Configuration -----------------------------------------*/
539 hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
540 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
541 hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1) |
542 hsai->FrameInit.FSOffset |
543 hsai->FrameInit.FSDefinition |
544 hsai->FrameInit.FSPolarity |
545 ((hsai->FrameInit.ActiveFrameLength - 1) << 8));
547 /* SAI Block_x SLOT Configuration ------------------------------------------*/
548 /* This register has no meaning in AC 97 and SPDIF audio protocol */
549 hsai->Instance->SLOTR&= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
550 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN ));
552 hsai->Instance->SLOTR|= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize
553 | (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1) << 8);
555 /* Initialize the error code */
556 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
558 /* Initialize the SAI state */
559 hsai->State= HAL_SAI_STATE_READY;
561 /* Release Lock */
562 __HAL_UNLOCK(hsai);
564 return HAL_OK;
568 * @brief DeInitialize the SAI peripheral.
569 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
570 * the configuration information for SAI module.
571 * @retval HAL status
573 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
575 /* Check the SAI handle allocation */
576 if(hsai == NULL)
578 return HAL_ERROR;
581 hsai->State = HAL_SAI_STATE_BUSY;
583 /* Disabled All interrupt and clear all the flag */
584 hsai->Instance->IMR = 0;
585 hsai->Instance->CLRFR = 0xFFFFFFFFU;
587 /* Disable the SAI */
588 SAI_Disable(hsai);
590 /* Flush the fifo */
591 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
593 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
594 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
595 if (hsai->MspDeInitCallback == NULL)
597 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
599 hsai->MspDeInitCallback(hsai);
600 #else
601 HAL_SAI_MspDeInit(hsai);
602 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
604 /* Initialize the error code */
605 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
607 /* Initialize the SAI state */
608 hsai->State = HAL_SAI_STATE_RESET;
610 /* Release Lock */
611 __HAL_UNLOCK(hsai);
613 return HAL_OK;
617 * @brief Initialize the SAI MSP.
618 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
619 * the configuration information for SAI module.
620 * @retval None
622 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
624 /* Prevent unused argument(s) compilation warning */
625 UNUSED(hsai);
627 /* NOTE : This function should not be modified, when the callback is needed,
628 the HAL_SAI_MspInit could be implemented in the user file
633 * @brief DeInitialize the SAI MSP.
634 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
635 * the configuration information for SAI module.
636 * @retval None
638 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
640 /* Prevent unused argument(s) compilation warning */
641 UNUSED(hsai);
643 /* NOTE : This function should not be modified, when the callback is needed,
644 the HAL_SAI_MspDeInit could be implemented in the user file
648 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
650 * @brief Register a user SAI callback
651 * to be used instead of the weak predefined callback.
652 * @param hsai SAI handle.
653 * @param CallbackID ID of the callback to be registered.
654 * This parameter can be one of the following values:
655 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
656 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
657 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
658 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
659 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
660 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
661 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
662 * @param pCallback pointer to the callback function.
663 * @retval HAL status.
665 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
666 HAL_SAI_CallbackIDTypeDef CallbackID,
667 pSAI_CallbackTypeDef pCallback)
669 HAL_StatusTypeDef status = HAL_OK;
671 if (pCallback == NULL)
673 /* update the error code */
674 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
675 /* update return status */
676 status = HAL_ERROR;
678 else
680 if (HAL_SAI_STATE_READY == hsai->State)
682 switch (CallbackID)
684 case HAL_SAI_RX_COMPLETE_CB_ID :
685 hsai->RxCpltCallback = pCallback;
686 break;
687 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
688 hsai->RxHalfCpltCallback = pCallback;
689 break;
690 case HAL_SAI_TX_COMPLETE_CB_ID :
691 hsai->TxCpltCallback = pCallback;
692 break;
693 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
694 hsai->TxHalfCpltCallback = pCallback;
695 break;
696 case HAL_SAI_ERROR_CB_ID :
697 hsai->ErrorCallback = pCallback;
698 break;
699 case HAL_SAI_MSPINIT_CB_ID :
700 hsai->MspInitCallback = pCallback;
701 break;
702 case HAL_SAI_MSPDEINIT_CB_ID :
703 hsai->MspDeInitCallback = pCallback;
704 break;
705 default :
706 /* update the error code */
707 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
708 /* update return status */
709 status = HAL_ERROR;
710 break;
713 else if (HAL_SAI_STATE_RESET == hsai->State)
715 switch (CallbackID)
717 case HAL_SAI_MSPINIT_CB_ID :
718 hsai->MspInitCallback = pCallback;
719 break;
720 case HAL_SAI_MSPDEINIT_CB_ID :
721 hsai->MspDeInitCallback = pCallback;
722 break;
723 default :
724 /* update the error code */
725 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
726 /* update return status */
727 status = HAL_ERROR;
728 break;
731 else
733 /* update the error code */
734 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
735 /* update return status */
736 status = HAL_ERROR;
739 return status;
743 * @brief Unregister a user SAI callback.
744 * SAI callback is redirected to the weak predefined callback.
745 * @param hsai SAI handle.
746 * @param CallbackID ID of the callback to be unregistered.
747 * This parameter can be one of the following values:
748 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
749 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
750 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
751 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
752 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
753 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
754 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
755 * @retval HAL status.
757 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
758 HAL_SAI_CallbackIDTypeDef CallbackID)
760 HAL_StatusTypeDef status = HAL_OK;
762 if (HAL_SAI_STATE_READY == hsai->State)
764 switch (CallbackID)
766 case HAL_SAI_RX_COMPLETE_CB_ID :
767 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
768 break;
769 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
770 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
771 break;
772 case HAL_SAI_TX_COMPLETE_CB_ID :
773 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
774 break;
775 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
776 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
777 break;
778 case HAL_SAI_ERROR_CB_ID :
779 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
780 break;
781 case HAL_SAI_MSPINIT_CB_ID :
782 hsai->MspInitCallback = HAL_SAI_MspInit;
783 break;
784 case HAL_SAI_MSPDEINIT_CB_ID :
785 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
786 break;
787 default :
788 /* update the error code */
789 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
790 /* update return status */
791 status = HAL_ERROR;
792 break;
795 else if (HAL_SAI_STATE_RESET == hsai->State)
797 switch (CallbackID)
799 case HAL_SAI_MSPINIT_CB_ID :
800 hsai->MspInitCallback = HAL_SAI_MspInit;
801 break;
802 case HAL_SAI_MSPDEINIT_CB_ID :
803 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
804 break;
805 default :
806 /* update the error code */
807 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
808 /* update return status */
809 status = HAL_ERROR;
810 break;
813 else
815 /* update the error code */
816 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
817 /* update return status */
818 status = HAL_ERROR;
820 return status;
822 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
825 * @}
828 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
829 * @brief Data transfers functions
831 @verbatim
832 ==============================================================================
833 ##### IO operation functions #####
834 ==============================================================================
835 [..]
836 This subsection provides a set of functions allowing to manage the SAI data
837 transfers.
839 (+) There are two modes of transfer:
840 (++) Blocking mode : The communication is performed in the polling mode.
841 The status of all data processing is returned by the same function
842 after finishing transfer.
843 (++) No-Blocking mode : The communication is performed using Interrupts
844 or DMA. These functions return the status of the transfer startup.
845 The end of the data processing will be indicated through the
846 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
847 using DMA mode.
849 (+) Blocking mode functions are :
850 (++) HAL_SAI_Transmit()
851 (++) HAL_SAI_Receive()
853 (+) Non Blocking mode functions with Interrupt are :
854 (++) HAL_SAI_Transmit_IT()
855 (++) HAL_SAI_Receive_IT()
857 (+) Non Blocking mode functions with DMA are :
858 (++) HAL_SAI_Transmit_DMA()
859 (++) HAL_SAI_Receive_DMA()
861 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
862 (++) HAL_SAI_TxCpltCallback()
863 (++) HAL_SAI_RxCpltCallback()
864 (++) HAL_SAI_ErrorCallback()
866 @endverbatim
867 * @{
871 * @brief Transmit an amount of data in blocking mode.
872 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
873 * the configuration information for SAI module.
874 * @param pData Pointer to data buffer
875 * @param Size Amount of data to be sent
876 * @param Timeout Timeout duration
877 * @retval HAL status
879 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)
881 uint32_t tickstart = HAL_GetTick();
883 if((pData == NULL ) || (Size == 0))
885 return HAL_ERROR;
888 if(hsai->State == HAL_SAI_STATE_READY)
890 /* Process Locked */
891 __HAL_LOCK(hsai);
893 hsai->XferSize = Size;
894 hsai->XferCount = Size;
895 hsai->pBuffPtr = pData;
896 hsai->State = HAL_SAI_STATE_BUSY_TX;
897 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
899 /* Check if the SAI is already enabled */
900 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
902 /* fill the fifo with data before to enabled the SAI */
903 SAI_FillFifo(hsai);
904 /* Enable SAI peripheral */
905 __HAL_SAI_ENABLE(hsai);
908 while(hsai->XferCount > 0)
910 /* Write data if the FIFO is not full */
911 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
913 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
915 hsai->Instance->DR = (*hsai->pBuffPtr++);
917 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
919 hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
920 hsai->pBuffPtr+= 2;
922 else
924 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
925 hsai->pBuffPtr+= 4;
927 hsai->XferCount--;
929 else
931 /* Check for the Timeout */
932 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0)||((HAL_GetTick() - tickstart) > Timeout)))
934 /* Update error code */
935 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
937 /* Clear all the flags */
938 hsai->Instance->CLRFR = 0xFFFFFFFFU;
940 /* Disable SAI peripheral */
941 SAI_Disable(hsai);
943 /* Flush the fifo */
944 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
946 /* Change the SAI state */
947 hsai->State = HAL_SAI_STATE_READY;
949 /* Process Unlocked */
950 __HAL_UNLOCK(hsai);
952 return HAL_ERROR;
957 hsai->State = HAL_SAI_STATE_READY;
959 /* Process Unlocked */
960 __HAL_UNLOCK(hsai);
962 return HAL_OK;
964 else
966 return HAL_BUSY;
971 * @brief Receive an amount of data in blocking mode.
972 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
973 * the configuration information for SAI module.
974 * @param pData Pointer to data buffer
975 * @param Size Amount of data to be received
976 * @param Timeout Timeout duration
977 * @retval HAL status
979 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
981 uint32_t tickstart = HAL_GetTick();
983 if((pData == NULL ) || (Size == 0))
985 return HAL_ERROR;
988 if(hsai->State == HAL_SAI_STATE_READY)
990 /* Process Locked */
991 __HAL_LOCK(hsai);
993 hsai->pBuffPtr = pData;
994 hsai->XferSize = Size;
995 hsai->XferCount = Size;
996 hsai->State = HAL_SAI_STATE_BUSY_RX;
997 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
999 /* Check if the SAI is already enabled */
1000 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1002 /* Enable SAI peripheral */
1003 __HAL_SAI_ENABLE(hsai);
1006 /* Receive data */
1007 while(hsai->XferCount > 0)
1009 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1011 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1013 (*hsai->pBuffPtr++) = hsai->Instance->DR;
1015 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1017 *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;
1018 hsai->pBuffPtr+= 2;
1020 else
1022 *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;
1023 hsai->pBuffPtr+= 4;
1025 hsai->XferCount--;
1027 else
1029 /* Check for the Timeout */
1030 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0)||((HAL_GetTick() - tickstart) > Timeout)))
1032 /* Update error code */
1033 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1035 /* Clear all the flags */
1036 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1038 /* Disable SAI peripheral */
1039 SAI_Disable(hsai);
1041 /* Flush the fifo */
1042 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1044 /* Change the SAI state */
1045 hsai->State = HAL_SAI_STATE_READY;
1047 /* Process Unlocked */
1048 __HAL_UNLOCK(hsai);
1050 return HAL_ERROR;
1055 hsai->State = HAL_SAI_STATE_READY;
1057 /* Process Unlocked */
1058 __HAL_UNLOCK(hsai);
1060 return HAL_OK;
1062 else
1064 return HAL_BUSY;
1069 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1070 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1071 * the configuration information for SAI module.
1072 * @param pData Pointer to data buffer
1073 * @param Size Amount of data to be sent
1074 * @retval HAL status
1076 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1078 if((pData == NULL) || (Size == 0))
1080 return HAL_ERROR;
1083 if(hsai->State == HAL_SAI_STATE_READY)
1085 /* Process Locked */
1086 __HAL_LOCK(hsai);
1088 hsai->pBuffPtr = pData;
1089 hsai->XferSize = Size;
1090 hsai->XferCount = Size;
1091 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1092 hsai->State = HAL_SAI_STATE_BUSY_TX;
1094 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1096 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1098 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1100 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1102 else
1104 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1107 /* Fill the fifo before starting the communication */
1108 SAI_FillFifo(hsai);
1110 /* Enable FRQ and OVRUDR interrupts */
1111 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1113 /* Check if the SAI is already enabled */
1114 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1116 /* Enable SAI peripheral */
1117 __HAL_SAI_ENABLE(hsai);
1119 /* Process Unlocked */
1120 __HAL_UNLOCK(hsai);
1122 return HAL_OK;
1124 else
1126 return HAL_BUSY;
1131 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1132 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1133 * the configuration information for SAI module.
1134 * @param pData Pointer to data buffer
1135 * @param Size Amount of data to be received
1136 * @retval HAL status
1138 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1140 if((pData == NULL) || (Size == 0))
1142 return HAL_ERROR;
1145 if(hsai->State == HAL_SAI_STATE_READY)
1147 /* Process Locked */
1148 __HAL_LOCK(hsai);
1150 hsai->pBuffPtr = pData;
1151 hsai->XferSize = Size;
1152 hsai->XferCount = Size;
1153 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1154 hsai->State = HAL_SAI_STATE_BUSY_RX;
1156 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1158 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1160 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1162 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1164 else
1166 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1169 /* Enable TXE and OVRUDR interrupts */
1170 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1172 /* Check if the SAI is already enabled */
1173 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1175 /* Enable SAI peripheral */
1176 __HAL_SAI_ENABLE(hsai);
1179 /* Process Unlocked */
1180 __HAL_UNLOCK(hsai);
1182 return HAL_OK;
1184 else
1186 return HAL_BUSY;
1191 * @brief Pause the audio stream playing from the Media.
1192 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1193 * the configuration information for SAI module.
1194 * @retval HAL status
1196 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1198 /* Process Locked */
1199 __HAL_LOCK(hsai);
1201 /* Pause the audio file playing by disabling the SAI DMA requests */
1202 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1204 /* Process Unlocked */
1205 __HAL_UNLOCK(hsai);
1207 return HAL_OK;
1211 * @brief Resume the audio stream playing from the Media.
1212 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1213 * the configuration information for SAI module.
1214 * @retval HAL status
1216 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1218 /* Process Locked */
1219 __HAL_LOCK(hsai);
1221 /* Enable the SAI DMA requests */
1222 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1224 /* If the SAI peripheral is still not enabled, enable it */
1225 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1227 /* Enable SAI peripheral */
1228 __HAL_SAI_ENABLE(hsai);
1231 /* Process Unlocked */
1232 __HAL_UNLOCK(hsai);
1234 return HAL_OK;
1238 * @brief Stop the audio stream playing from the Media.
1239 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1240 * the configuration information for SAI module.
1241 * @retval HAL status
1243 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1245 HAL_StatusTypeDef status = HAL_OK;
1247 /* Process Locked */
1248 __HAL_LOCK(hsai);
1250 /* Disable the SAI DMA request */
1251 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1253 /* Abort the SAI Tx DMA Stream */
1254 if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1256 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1258 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1259 if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1261 status = HAL_ERROR;
1262 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1267 /* Abort the SAI Rx DMA Stream */
1268 if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1270 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1272 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1273 if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1275 status = HAL_ERROR;
1276 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1281 /* Disable SAI peripheral */
1282 SAI_Disable(hsai);
1284 /* Flush the fifo */
1285 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1287 /* Set hsai state to ready */
1288 hsai->State = HAL_SAI_STATE_READY;
1290 /* Process Unlocked */
1291 __HAL_UNLOCK(hsai);
1293 return status;
1297 * @brief Abort the current transfer and disable the SAI.
1298 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1299 * the configuration information for SAI module.
1300 * @retval HAL status
1302 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1304 HAL_StatusTypeDef status = HAL_OK;
1306 /* Process Locked */
1307 __HAL_LOCK(hsai);
1309 /* Check SAI DMA is enabled or not */
1310 if((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1312 /* Disable the SAI DMA request */
1313 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1315 /* Abort the SAI Tx DMA Stream */
1316 if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1318 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1320 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1321 if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1323 status = HAL_ERROR;
1324 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1329 /* Abort the SAI Rx DMA Stream */
1330 if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1332 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1334 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1335 if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1337 status = HAL_ERROR;
1338 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1343 /* Disabled All interrupt and clear all the flag */
1344 hsai->Instance->IMR = 0;
1345 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1347 /* Disable SAI peripheral */
1348 SAI_Disable(hsai);
1350 /* Flush the fifo */
1351 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1353 /* Set hsai state to ready */
1354 hsai->State = HAL_SAI_STATE_READY;
1356 /* Process Unlocked */
1357 __HAL_UNLOCK(hsai);
1359 return status;
1363 * @brief Transmit an amount of data in non-blocking mode with DMA.
1364 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1365 * the configuration information for SAI module.
1366 * @param pData Pointer to data buffer
1367 * @param Size Amount of data to be sent
1368 * @retval HAL status
1370 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1372 if((pData == NULL) || (Size == 0))
1374 return HAL_ERROR;
1377 if(hsai->State == HAL_SAI_STATE_READY)
1379 /* Process Locked */
1380 __HAL_LOCK(hsai);
1382 hsai->pBuffPtr = pData;
1383 hsai->XferSize = Size;
1384 hsai->XferCount = Size;
1385 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1386 hsai->State = HAL_SAI_STATE_BUSY_TX;
1388 /* Set the SAI Tx DMA Half transfer complete callback */
1389 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1391 /* Set the SAI TxDMA transfer complete callback */
1392 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1394 /* Set the DMA error callback */
1395 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1397 /* Set the DMA Tx abort callback */
1398 hsai->hdmatx->XferAbortCallback = NULL;
1400 /* Enable the Tx DMA Stream */
1401 if(HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1403 __HAL_UNLOCK(hsai);
1404 return HAL_ERROR;
1407 /* Check if the SAI is already enabled */
1408 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1410 /* Enable SAI peripheral */
1411 __HAL_SAI_ENABLE(hsai);
1414 /* Enable the interrupts for error handling */
1415 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1417 /* Enable SAI Tx DMA Request */
1418 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1420 /* Process Unlocked */
1421 __HAL_UNLOCK(hsai);
1423 return HAL_OK;
1425 else
1427 return HAL_BUSY;
1432 * @brief Receive an amount of data in non-blocking mode with DMA.
1433 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1434 * the configuration information for SAI module.
1435 * @param pData Pointer to data buffer
1436 * @param Size Amount of data to be received
1437 * @retval HAL status
1439 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1442 if((pData == NULL) || (Size == 0))
1444 return HAL_ERROR;
1447 if(hsai->State == HAL_SAI_STATE_READY)
1449 /* Process Locked */
1450 __HAL_LOCK(hsai);
1452 hsai->pBuffPtr = pData;
1453 hsai->XferSize = Size;
1454 hsai->XferCount = Size;
1455 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1456 hsai->State = HAL_SAI_STATE_BUSY_RX;
1458 /* Set the SAI Rx DMA Half transfer complete callback */
1459 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1461 /* Set the SAI Rx DMA transfer complete callback */
1462 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1464 /* Set the DMA error callback */
1465 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1467 /* Set the DMA Rx abort callback */
1468 hsai->hdmarx->XferAbortCallback = NULL;
1470 /* Enable the Rx DMA Stream */
1471 if(HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1473 __HAL_UNLOCK(hsai);
1474 return HAL_ERROR;
1477 /* Check if the SAI is already enabled */
1478 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1480 /* Enable SAI peripheral */
1481 __HAL_SAI_ENABLE(hsai);
1484 /* Enable the interrupts for error handling */
1485 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1487 /* Enable SAI Rx DMA Request */
1488 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1490 /* Process Unlocked */
1491 __HAL_UNLOCK(hsai);
1493 return HAL_OK;
1495 else
1497 return HAL_BUSY;
1502 * @brief Enable the Tx mute mode.
1503 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1504 * the configuration information for SAI module.
1505 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1506 * @retval HAL status
1508 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1510 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1512 if(hsai->State != HAL_SAI_STATE_RESET)
1514 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1515 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
1516 return HAL_OK;
1518 return HAL_ERROR;
1522 * @brief Disable the Tx mute mode.
1523 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1524 * the configuration information for SAI module.
1525 * @retval HAL status
1527 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1529 if(hsai->State != HAL_SAI_STATE_RESET)
1531 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1532 return HAL_OK;
1534 return HAL_ERROR;
1538 * @brief Enable the Rx mute detection.
1539 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1540 * the configuration information for SAI module.
1541 * @param callback function called when the mute is detected.
1542 * @param counter number a data before mute detection max 63.
1543 * @retval HAL status
1545 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1547 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1549 if(hsai->State != HAL_SAI_STATE_RESET)
1551 /* set the mute counter */
1552 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1553 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1554 hsai->mutecallback = callback;
1555 /* enable the IT interrupt */
1556 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1557 return HAL_OK;
1559 return HAL_ERROR;
1563 * @brief Disable the Rx mute detection.
1564 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1565 * the configuration information for SAI module.
1566 * @retval HAL status
1568 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1570 if(hsai->State != HAL_SAI_STATE_RESET)
1572 /* set the mutecallback to NULL */
1573 hsai->mutecallback = (SAIcallback)NULL;
1574 /* enable the IT interrupt */
1575 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1576 return HAL_OK;
1578 return HAL_ERROR;
1582 * @brief Handle SAI interrupt request.
1583 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1584 * the configuration information for SAI module.
1585 * @retval None
1587 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1589 if(hsai->State != HAL_SAI_STATE_RESET)
1591 uint32_t itflags = hsai->Instance->SR;
1592 uint32_t itsources = hsai->Instance->IMR;
1593 uint32_t cr1config = hsai->Instance->CR1;
1594 uint32_t tmperror;
1596 /* SAI Fifo request interrupt occurred ------------------------------------*/
1597 if(((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1599 hsai->InterruptServiceRoutine(hsai);
1601 /* SAI Overrun error interrupt occurred ----------------------------------*/
1602 else if(((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1604 /* Clear the SAI Overrun flag */
1605 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1606 /* Get the SAI error code */
1607 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1608 /* Change the SAI error code */
1609 hsai->ErrorCode |= tmperror;
1610 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1611 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1612 hsai->ErrorCallback(hsai);
1613 #else
1614 HAL_SAI_ErrorCallback(hsai);
1615 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1617 /* SAI mutedet interrupt occurred ----------------------------------*/
1618 else if(((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1620 /* Clear the SAI mutedet flag */
1621 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1622 /* call the call back function */
1623 if(hsai->mutecallback != (SAIcallback)NULL)
1625 /* inform the user that an RX mute event has been detected */
1626 hsai->mutecallback();
1629 /* SAI AFSDET interrupt occurred ----------------------------------*/
1630 else if(((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1632 /* Change the SAI error code */
1633 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1634 /* Check SAI DMA is enabled or not */
1635 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1637 /* Abort the SAI DMA Streams */
1638 if(hsai->hdmatx != NULL)
1640 /* Set the DMA Tx abort callback */
1641 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1643 /* Abort DMA in IT mode */
1644 HAL_DMA_Abort_IT(hsai->hdmatx);
1646 else if(hsai->hdmarx != NULL)
1648 /* Set the DMA Rx abort callback */
1649 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1650 /* Abort DMA in IT mode */
1651 HAL_DMA_Abort_IT(hsai->hdmarx);
1654 else
1656 /* Abort SAI */
1657 HAL_SAI_Abort(hsai);
1659 /* Set error callback */
1660 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1661 hsai->ErrorCallback(hsai);
1662 #else
1663 HAL_SAI_ErrorCallback(hsai);
1664 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1667 /* SAI LFSDET interrupt occurred ----------------------------------*/
1668 else if(((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1670 /* Change the SAI error code */
1671 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1673 /* Check SAI DMA is enabled or not */
1674 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1676 /* Abort the SAI DMA Streams */
1677 if(hsai->hdmatx != NULL)
1679 /* Set the DMA Tx abort callback */
1680 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1681 /* Abort DMA in IT mode */
1682 HAL_DMA_Abort_IT(hsai->hdmatx);
1684 else if(hsai->hdmarx != NULL)
1686 /* Set the DMA Rx abort callback */
1687 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1688 /* Abort DMA in IT mode */
1689 HAL_DMA_Abort_IT(hsai->hdmarx);
1692 else
1694 /* Abort SAI */
1695 HAL_SAI_Abort(hsai);
1697 /* Set error callback */
1698 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1699 hsai->ErrorCallback(hsai);
1700 #else
1701 HAL_SAI_ErrorCallback(hsai);
1702 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1705 /* SAI WCKCFG interrupt occurred ----------------------------------*/
1706 else if(((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1708 /* Change the SAI error code */
1709 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1711 /* Abort the SAI DMA Streams */
1712 if(hsai->hdmatx != NULL)
1714 /* Set the DMA Tx abort callback */
1715 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1716 /* Abort DMA in IT mode */
1717 HAL_DMA_Abort_IT(hsai->hdmatx);
1719 else if(hsai->hdmarx != NULL)
1721 /* Set the DMA Rx abort callback */
1722 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1723 /* Abort DMA in IT mode */
1724 HAL_DMA_Abort_IT(hsai->hdmarx);
1726 else
1728 /* If WCKCFG occurs, SAI audio block is automatically disabled */
1729 /* Disable all interrupts and clear all flags */
1730 hsai->Instance->IMR = 0U;
1731 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1732 /* Set the SAI state to ready to be able to start again the process */
1733 hsai->State = HAL_SAI_STATE_READY;
1735 /* Initialize XferCount */
1736 hsai->XferCount = 0U;
1738 /* SAI error Callback */
1739 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1740 hsai->ErrorCallback(hsai);
1741 #else
1742 HAL_SAI_ErrorCallback(hsai);
1743 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1746 /* SAI CNRDY interrupt occurred ----------------------------------*/
1747 else if(((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1749 /* Clear the SAI CNRDY flag */
1750 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1751 /* Change the SAI error code */
1752 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1753 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1754 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1755 hsai->ErrorCallback(hsai);
1756 #else
1757 HAL_SAI_ErrorCallback(hsai);
1758 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1760 else
1762 /* Nothing to do */
1768 * @brief Tx Transfer completed callback.
1769 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1770 * the configuration information for SAI module.
1771 * @retval None
1773 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1775 /* Prevent unused argument(s) compilation warning */
1776 UNUSED(hsai);
1778 /* NOTE : This function should not be modified, when the callback is needed,
1779 the HAL_SAI_TxCpltCallback could be implemented in the user file
1784 * @brief Tx Transfer Half completed callback.
1785 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1786 * the configuration information for SAI module.
1787 * @retval None
1789 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1791 /* Prevent unused argument(s) compilation warning */
1792 UNUSED(hsai);
1794 /* NOTE : This function should not be modified, when the callback is needed,
1795 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1800 * @brief Rx Transfer completed callback.
1801 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1802 * the configuration information for SAI module.
1803 * @retval None
1805 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
1807 /* Prevent unused argument(s) compilation warning */
1808 UNUSED(hsai);
1810 /* NOTE : This function should not be modified, when the callback is needed,
1811 the HAL_SAI_RxCpltCallback could be implemented in the user file
1816 * @brief Rx Transfer half completed callback.
1817 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1818 * the configuration information for SAI module.
1819 * @retval None
1821 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1823 /* Prevent unused argument(s) compilation warning */
1824 UNUSED(hsai);
1826 /* NOTE : This function should not be modified, when the callback is needed,
1827 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
1832 * @brief SAI error callback.
1833 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1834 * the configuration information for SAI module.
1835 * @retval None
1837 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
1839 /* Prevent unused argument(s) compilation warning */
1840 UNUSED(hsai);
1842 /* NOTE : This function should not be modified, when the callback is needed,
1843 the HAL_SAI_ErrorCallback could be implemented in the user file
1848 * @}
1851 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
1852 * @brief Peripheral State functions
1854 @verbatim
1855 ===============================================================================
1856 ##### Peripheral State and Errors functions #####
1857 ===============================================================================
1858 [..]
1859 This subsection permits to get in run-time the status of the peripheral
1860 and the data flow.
1862 @endverbatim
1863 * @{
1867 * @brief Return the SAI handle state.
1868 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1869 * the configuration information for SAI module.
1870 * @retval HAL state
1872 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
1874 return hsai->State;
1878 * @brief Return the SAI error code.
1879 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1880 * the configuration information for the specified SAI Block.
1881 * @retval SAI Error Code
1883 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
1885 return hsai->ErrorCode;
1889 * @}
1893 * @}
1896 /** @addtogroup SAI_Private_Functions
1897 * @brief Private functions
1898 * @{
1902 * @brief Initialize the SAI I2S protocol according to the specified parameters
1903 * in the SAI_InitTypeDef and create the associated handle.
1904 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1905 * the configuration information for SAI module.
1906 * @param protocol one of the supported protocol.
1907 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
1908 * the configuration information for SAI module.
1909 * @param nbslot number of slot minimum value is 2 and max is 16.
1910 * the value must be a multiple of 2.
1911 * @retval HAL status
1913 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
1915 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
1916 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
1917 /* Compute ClockStrobing according AudioMode */
1918 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1919 { /* Transmit */
1920 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1922 else
1923 { /* Receive */
1924 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1926 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1927 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
1928 hsai->SlotInit.FirstBitOffset = 0;
1929 hsai->SlotInit.SlotNumber = nbslot;
1931 /* in IS2 the number of slot must be even */
1932 if((nbslot & 0x1) != 0 )
1934 return HAL_ERROR;
1937 switch(protocol)
1939 case SAI_I2S_STANDARD :
1940 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1941 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1942 break;
1943 case SAI_I2S_MSBJUSTIFIED :
1944 case SAI_I2S_LSBJUSTIFIED :
1945 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
1946 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
1947 break;
1948 default :
1949 return HAL_ERROR;
1952 /* Frame definition */
1953 switch(datasize)
1955 case SAI_PROTOCOL_DATASIZE_16BIT:
1956 hsai->Init.DataSize = SAI_DATASIZE_16;
1957 hsai->FrameInit.FrameLength = 32*(nbslot/2);
1958 hsai->FrameInit.ActiveFrameLength = 16*(nbslot/2);
1959 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
1960 break;
1961 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
1962 hsai->Init.DataSize = SAI_DATASIZE_16;
1963 hsai->FrameInit.FrameLength = 64*(nbslot/2);
1964 hsai->FrameInit.ActiveFrameLength = 32*(nbslot/2);
1965 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1966 break;
1967 case SAI_PROTOCOL_DATASIZE_24BIT:
1968 hsai->Init.DataSize = SAI_DATASIZE_24;
1969 hsai->FrameInit.FrameLength = 64*(nbslot/2);
1970 hsai->FrameInit.ActiveFrameLength = 32*(nbslot/2);
1971 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1972 break;
1973 case SAI_PROTOCOL_DATASIZE_32BIT:
1974 hsai->Init.DataSize = SAI_DATASIZE_32;
1975 hsai->FrameInit.FrameLength = 64*(nbslot/2);
1976 hsai->FrameInit.ActiveFrameLength = 32*(nbslot/2);
1977 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1978 break;
1979 default :
1980 return HAL_ERROR;
1982 if(protocol == SAI_I2S_LSBJUSTIFIED)
1984 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
1986 hsai->SlotInit.FirstBitOffset = 16;
1988 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
1990 hsai->SlotInit.FirstBitOffset = 8;
1993 return HAL_OK;
1997 * @brief Initialize the SAI PCM protocol according to the specified parameters
1998 * in the SAI_InitTypeDef and create the associated handle.
1999 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2000 * the configuration information for SAI module.
2001 * @param protocol one of the supported protocol
2002 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2003 * @param nbslot number of slot minimum value is 1 and the max is 16.
2004 * @retval HAL status
2006 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2008 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2009 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2010 /* Compute ClockStrobing according AudioMode */
2011 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2012 { /* Transmit */
2013 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2015 else
2016 { /* Receive */
2017 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2019 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2020 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2021 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2022 hsai->SlotInit.FirstBitOffset = 0;
2023 hsai->SlotInit.SlotNumber = nbslot;
2024 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2026 switch(protocol)
2028 case SAI_PCM_SHORT :
2029 hsai->FrameInit.ActiveFrameLength = 1;
2030 break;
2031 case SAI_PCM_LONG :
2032 hsai->FrameInit.ActiveFrameLength = 13;
2033 break;
2034 default :
2035 return HAL_ERROR;
2038 switch(datasize)
2040 case SAI_PROTOCOL_DATASIZE_16BIT:
2041 hsai->Init.DataSize = SAI_DATASIZE_16;
2042 hsai->FrameInit.FrameLength = 16 * nbslot;
2043 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2044 break;
2045 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2046 hsai->Init.DataSize = SAI_DATASIZE_16;
2047 hsai->FrameInit.FrameLength = 32 * nbslot;
2048 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2049 break;
2050 case SAI_PROTOCOL_DATASIZE_24BIT :
2051 hsai->Init.DataSize = SAI_DATASIZE_24;
2052 hsai->FrameInit.FrameLength = 32 * nbslot;
2053 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2054 break;
2055 case SAI_PROTOCOL_DATASIZE_32BIT:
2056 hsai->Init.DataSize = SAI_DATASIZE_32;
2057 hsai->FrameInit.FrameLength = 32 * nbslot;
2058 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2059 break;
2060 default :
2061 return HAL_ERROR;
2064 return HAL_OK;
2068 * @brief Fill the fifo.
2069 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2070 * the configuration information for SAI module.
2071 * @retval None
2073 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2075 /* fill the fifo with data before to enabled the SAI */
2076 while(((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0))
2078 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2080 hsai->Instance->DR = (*hsai->pBuffPtr++);
2082 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
2084 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2085 hsai->pBuffPtr+= 2;
2087 else
2089 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
2090 hsai->pBuffPtr+= 4;
2092 hsai->XferCount--;
2097 * @brief Return the interrupt flag to set according the SAI setup.
2098 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2099 * the configuration information for SAI module.
2100 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2101 * @retval the list of the IT flag to enable
2103 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
2105 uint32_t tmpIT = SAI_IT_OVRUDR;
2107 if(mode == SAI_MODE_IT)
2109 tmpIT|= SAI_IT_FREQ;
2112 if((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2113 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2115 tmpIT|= SAI_IT_CNRDY;
2118 if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2120 tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;
2122 else
2124 /* hsai has been configured in master mode */
2125 tmpIT|= SAI_IT_WCKCFG;
2127 return tmpIT;
2131 * @brief Disable the SAI and wait for the disabling.
2132 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2133 * the configuration information for SAI module.
2134 * @retval None
2136 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2138 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock /7/1000);
2139 HAL_StatusTypeDef status = HAL_OK;
2141 /* Disable the SAI instance */
2142 __HAL_SAI_DISABLE(hsai);
2146 /* Check for the Timeout */
2147 if (count-- == 0)
2149 /* Update error code */
2150 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2151 status = HAL_TIMEOUT;
2152 break;
2154 } while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
2156 return status;
2160 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2161 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2162 * the configuration information for SAI module.
2163 * @retval None
2165 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2167 if(hsai->XferCount == 0)
2169 /* Handle the end of the transmission */
2170 /* Disable FREQ and OVRUDR interrupts */
2171 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2172 hsai->State = HAL_SAI_STATE_READY;
2173 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2174 hsai->TxCpltCallback(hsai);
2175 #else
2176 HAL_SAI_TxCpltCallback(hsai);
2177 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2179 else
2181 /* Write data on DR register */
2182 hsai->Instance->DR = (*hsai->pBuffPtr++);
2183 hsai->XferCount--;
2188 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2189 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2190 * the configuration information for SAI module.
2191 * @retval None
2193 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2195 if(hsai->XferCount == 0)
2197 /* Handle the end of the transmission */
2198 /* Disable FREQ and OVRUDR interrupts */
2199 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2200 hsai->State = HAL_SAI_STATE_READY;
2201 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2202 hsai->TxCpltCallback(hsai);
2203 #else
2204 HAL_SAI_TxCpltCallback(hsai);
2205 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2207 else
2209 /* Write data on DR register */
2210 hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
2211 hsai->pBuffPtr+=2;
2212 hsai->XferCount--;
2217 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2218 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2219 * the configuration information for SAI module.
2220 * @retval None
2222 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2224 if(hsai->XferCount == 0)
2226 /* Handle the end of the transmission */
2227 /* Disable FREQ and OVRUDR interrupts */
2228 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2229 hsai->State = HAL_SAI_STATE_READY;
2230 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2231 hsai->TxCpltCallback(hsai);
2232 #else
2233 HAL_SAI_TxCpltCallback(hsai);
2234 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2236 else
2238 /* Write data on DR register */
2239 hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
2240 hsai->pBuffPtr+=4;
2241 hsai->XferCount--;
2246 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2247 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2248 * the configuration information for SAI module.
2249 * @retval None
2251 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2253 /* Receive data */
2254 (*hsai->pBuffPtr++) = hsai->Instance->DR;
2255 hsai->XferCount--;
2257 /* Check end of the transfer */
2258 if(hsai->XferCount == 0)
2260 /* Disable TXE and OVRUDR interrupts */
2261 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2263 /* Clear the SAI Overrun flag */
2264 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2266 hsai->State = HAL_SAI_STATE_READY;
2267 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2268 hsai->RxCpltCallback(hsai);
2269 #else
2270 HAL_SAI_RxCpltCallback(hsai);
2271 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2276 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2277 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2278 * the configuration information for SAI module.
2279 * @retval None
2281 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2283 /* Receive data */
2284 *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;
2285 hsai->pBuffPtr+=2;
2286 hsai->XferCount--;
2288 /* Check end of the transfer */
2289 if(hsai->XferCount == 0)
2291 /* Disable TXE and OVRUDR interrupts */
2292 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2294 /* Clear the SAI Overrun flag */
2295 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2297 hsai->State = HAL_SAI_STATE_READY;
2298 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2299 hsai->RxCpltCallback(hsai);
2300 #else
2301 HAL_SAI_RxCpltCallback(hsai);
2302 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2307 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2308 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2309 * the configuration information for SAI module.
2310 * @retval None
2312 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2314 /* Receive data */
2315 *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;
2316 hsai->pBuffPtr+=4;
2317 hsai->XferCount--;
2319 /* Check end of the transfer */
2320 if(hsai->XferCount == 0)
2322 /* Disable TXE and OVRUDR interrupts */
2323 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2325 /* Clear the SAI Overrun flag */
2326 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2328 hsai->State = HAL_SAI_STATE_READY;
2329 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2330 hsai->RxCpltCallback(hsai);
2331 #else
2332 HAL_SAI_RxCpltCallback(hsai);
2333 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2338 * @brief DMA SAI transmit process complete callback.
2339 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2340 * the configuration information for the specified DMA module.
2341 * @retval None
2343 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2345 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
2347 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
2349 hsai->XferCount = 0;
2351 /* Disable SAI Tx DMA Request */
2352 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2354 /* Stop the interrupts error handling */
2355 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2357 hsai->State= HAL_SAI_STATE_READY;
2359 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2360 hsai->TxCpltCallback(hsai);
2361 #else
2362 HAL_SAI_TxCpltCallback(hsai);
2363 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2367 * @brief DMA SAI transmit process half complete callback.
2368 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2369 * the configuration information for the specified DMA module.
2370 * @retval None
2372 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2374 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2376 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2377 hsai->TxHalfCpltCallback(hsai);
2378 #else
2379 HAL_SAI_TxHalfCpltCallback(hsai);
2380 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2384 * @brief DMA SAI receive process complete callback.
2385 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2386 * the configuration information for the specified DMA module.
2387 * @retval None
2389 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2391 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2393 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
2395 /* Disable Rx DMA Request */
2396 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2397 hsai->XferCount = 0;
2399 /* Stop the interrupts error handling */
2400 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2402 hsai->State = HAL_SAI_STATE_READY;
2404 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2405 hsai->RxCpltCallback(hsai);
2406 #else
2407 HAL_SAI_RxCpltCallback(hsai);
2408 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2412 * @brief DMA SAI receive process half complete callback
2413 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2414 * the configuration information for the specified DMA module.
2415 * @retval None
2417 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2419 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2421 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2422 hsai->RxHalfCpltCallback(hsai);
2423 #else
2424 HAL_SAI_RxHalfCpltCallback(hsai);
2425 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2429 * @brief DMA SAI communication error callback.
2430 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2431 * the configuration information for the specified DMA module.
2432 * @retval None
2434 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2436 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2438 /* Set SAI error code */
2439 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2441 if((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
2443 /* Disable the SAI DMA request */
2444 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2446 /* Disable SAI peripheral */
2447 SAI_Disable(hsai);
2449 /* Set the SAI state ready to be able to start again the process */
2450 hsai->State = HAL_SAI_STATE_READY;
2452 /* Initialize XferCount */
2453 hsai->XferCount = 0U;
2455 /* SAI error Callback */
2456 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2457 hsai->ErrorCallback(hsai);
2458 #else
2459 HAL_SAI_ErrorCallback(hsai);
2460 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2464 * @brief DMA SAI Abort callback.
2465 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2466 * the configuration information for the specified DMA module.
2467 * @retval None
2469 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2471 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2473 /* Disable DMA request */
2474 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2476 /* Disable all interrupts and clear all flags */
2477 hsai->Instance->IMR = 0U;
2478 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2480 if(hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2482 /* Disable SAI peripheral */
2483 SAI_Disable(hsai);
2485 /* Flush the fifo */
2486 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2488 /* Set the SAI state to ready to be able to start again the process */
2489 hsai->State = HAL_SAI_STATE_READY;
2491 /* Initialize XferCount */
2492 hsai->XferCount = 0U;
2494 /* SAI error Callback */
2495 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2496 hsai->ErrorCallback(hsai);
2497 #else
2498 HAL_SAI_ErrorCallback(hsai);
2499 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2503 * @}
2506 #endif /* HAL_SAI_MODULE_ENABLED */
2508 * @}
2512 * @}
2515 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/