Set blackbox file handler to NULL after closing file
[inav.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_sai.c
blob36e7ee93212a4b4e67d4be6fad8c14974d8206c8
1 /**
2 ******************************************************************************
3 * @file stm32h7xx_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 (+@) PLLSAI1CLK output is configured or
53 (+@) PLLSAI2CLK output is configured or
54 (+@) PLLSAI3CLK output is configured or
55 (+@) PLLSAI4ACLK output is configured or
56 (+@) PLLSAI4BCLK output is configured or
57 (+@) External clock source is configured after setting correctly
58 the define constant EXTERNAL_CLOCK_VALUE in the stm32h7xx_hal_conf.h file.
60 [..]
61 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
62 for the external slaves even if there is no data in the FIFO, However FS signal
63 generation is conditioned by the presence of data in the FIFO.
65 [..]
66 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
67 and FS signal for the external slaves.
69 [..]
70 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
71 (+@) First bit Offset <= (SLOT size - Data size)
72 (+@) Data size <= SLOT size
73 (+@) Number of SLOT x SLOT size = Frame length
74 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
76 [..]
77 (@) PDM interface can be activated through HAL_SAI_Init function.
78 Please note that PDM interface is only available for SAI1 or SAI4 sub-block A.
79 PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
81 [..]
82 Three operation modes are available within this driver :
84 *** Polling mode IO operation ***
85 =================================
86 [..]
87 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
88 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
90 *** Interrupt mode IO operation ***
91 ===================================
92 [..]
93 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
94 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
95 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
96 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
97 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
98 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
99 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
100 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
102 *** DMA mode IO operation ***
103 =============================
104 [..]
105 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
106 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
107 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
108 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
109 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
110 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
111 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
112 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
113 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
114 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
115 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
117 *** SAI HAL driver additional function list ***
118 ===============================================
119 [..]
120 Below the list the others API available SAI HAL driver :
122 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
123 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
124 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
125 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
126 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
127 (+) HAL_SAI_Abort(): Abort the current transfer
129 *** SAI HAL driver macros list ***
130 ==================================
131 [..]
132 Below the list of most used macros in SAI HAL driver :
134 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
135 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
136 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
137 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
138 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
139 enabled or disabled
140 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
142 *** Callback registration ***
143 =============================
144 [..]
145 The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
146 allows the user to configure dynamically the driver callbacks.
147 Use functions HAL_SAI_RegisterCallback() to register a user callback.
149 [..]
150 Function HAL_SAI_RegisterCallback() allows to register following callbacks:
151 (+) RxCpltCallback : SAI receive complete.
152 (+) RxHalfCpltCallback : SAI receive half complete.
153 (+) TxCpltCallback : SAI transmit complete.
154 (+) TxHalfCpltCallback : SAI transmit half complete.
155 (+) ErrorCallback : SAI error.
156 (+) MspInitCallback : SAI MspInit.
157 (+) MspDeInitCallback : SAI MspDeInit.
158 [..]
159 This function takes as parameters the HAL peripheral handle, the callback ID
160 and a pointer to the user callback function.
162 [..]
163 Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
164 weak (surcharged) function.
165 HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
166 and the callback ID.
167 [..]
168 This function allows to reset following callbacks:
169 (+) RxCpltCallback : SAI receive complete.
170 (+) RxHalfCpltCallback : SAI receive half complete.
171 (+) TxCpltCallback : SAI transmit complete.
172 (+) TxHalfCpltCallback : SAI transmit half complete.
173 (+) ErrorCallback : SAI error.
174 (+) MspInitCallback : SAI MspInit.
175 (+) MspDeInitCallback : SAI MspDeInit.
177 [..]
178 By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
179 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
180 examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
181 Exception done for MspInit and MspDeInit callbacks that are respectively
182 reset to the legacy weak (surcharged) functions in the HAL_SAI_Init
183 and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
184 If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
185 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
187 [..]
188 Callbacks can be registered/unregistered in READY state only.
189 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
190 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
191 during the Init/DeInit.
192 In that case first register the MspInit/MspDeInit user callbacks
193 using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
194 or HAL_SAI_Init function.
196 [..]
197 When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
198 not defined, the callback registering feature is not available
199 and weak (surcharged) callbacks are used.
201 @endverbatim
202 ******************************************************************************
203 * @attention
205 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
206 * All rights reserved.</center></h2>
208 * This software component is licensed by ST under BSD 3-Clause license,
209 * the "License"; You may not use this file except in compliance with the
210 * License. You may obtain a copy of the License at:
211 * opensource.org/licenses/BSD-3-Clause
213 ******************************************************************************
216 /* Includes ------------------------------------------------------------------*/
217 #include "stm32h7xx_hal.h"
219 /** @addtogroup STM32H7xx_HAL_Driver
220 * @{
223 /** @defgroup SAI SAI
224 * @brief SAI HAL module driver
225 * @{
228 #ifdef HAL_SAI_MODULE_ENABLED
230 /* Private typedef -----------------------------------------------------------*/
231 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
232 * @{
234 typedef enum
236 SAI_MODE_DMA,
237 SAI_MODE_IT
238 } SAI_ModeTypedef;
240 * @}
243 /* Private define ------------------------------------------------------------*/
244 /** @defgroup SAI_Private_Constants SAI Private Constants
245 * @{
247 #define SAI_FIFO_SIZE 8U
248 #define SAI_DEFAULT_TIMEOUT 4U
249 #define SAI_LONG_TIMEOUT 1000U
251 * @}
254 /* Private macro -------------------------------------------------------------*/
255 /* Private variables ---------------------------------------------------------*/
256 /* Private function prototypes -----------------------------------------------*/
257 /** @defgroup SAI_Private_Functions SAI Private Functions
258 * @{
260 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
261 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
262 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
263 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
265 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
266 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
267 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
268 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
269 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
270 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
271 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
273 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
274 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
275 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
276 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
277 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
278 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
280 * @}
283 /* Exported functions ---------------------------------------------------------*/
284 /** @defgroup SAI_Exported_Functions SAI Exported Functions
285 * @{
288 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
289 * @brief Initialization and Configuration functions
291 @verbatim
292 ===============================================================================
293 ##### Initialization and de-initialization functions #####
294 ===============================================================================
295 [..] This subsection provides a set of functions allowing to initialize and
296 de-initialize the SAIx peripheral:
298 (+) User must implement HAL_SAI_MspInit() function in which he configures
299 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
301 (+) Call the function HAL_SAI_Init() to configure the selected device with
302 the selected configuration:
303 (++) Mode (Master/slave TX/RX)
304 (++) Protocol
305 (++) Data Size
306 (++) MCLK Output
307 (++) Audio frequency
308 (++) FIFO Threshold
309 (++) Frame Config
310 (++) Slot Config
311 (++) PDM Config
313 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
314 of the selected SAI peripheral.
316 @endverbatim
317 * @{
321 * @brief Initialize the structure FrameInit, SlotInit and the low part of
322 * Init according to the specified parameters and call the function
323 * HAL_SAI_Init to initialize the SAI block.
324 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
325 * the configuration information for SAI module.
326 * @param protocol one of the supported protocol @ref SAI_Protocol
327 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
328 * the configuration information for SAI module.
329 * @param nbslot Number of slot.
330 * @retval HAL status
332 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
334 HAL_StatusTypeDef status;
336 /* Check the parameters */
337 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
338 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
340 switch (protocol)
342 case SAI_I2S_STANDARD :
343 case SAI_I2S_MSBJUSTIFIED :
344 case SAI_I2S_LSBJUSTIFIED :
345 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
346 break;
347 case SAI_PCM_LONG :
348 case SAI_PCM_SHORT :
349 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
350 break;
351 default :
352 status = HAL_ERROR;
353 break;
356 if (status == HAL_OK)
358 status = HAL_SAI_Init(hsai);
361 return status;
365 * @brief Initialize the SAI according to the specified parameters.
366 * in the SAI_InitTypeDef structure and initialize the associated handle.
367 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
368 * the configuration information for SAI module.
369 * @retval HAL status
371 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
373 uint32_t tmpregisterGCR;
374 uint32_t ckstr_bits;
375 uint32_t syncen_bits;
376 SAI_TypeDef *SaiBaseAddress;
378 /* Check the SAI handle allocation */
379 if (hsai == NULL)
381 return HAL_ERROR;
384 /* check the instance */
385 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
387 /* Check the SAI Block parameters */
388 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
389 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
390 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
391 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
392 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
393 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
394 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
395 #if defined(SAI_VER_V2_X)
396 /* SAI Peripheral version depends on STM32H7 device revision ID */
397 if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
399 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
401 #else /* SAI_VER_V2_1 */
402 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
403 #endif /* SAI_VER_V2_X */
404 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
405 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
406 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
407 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
408 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
409 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
410 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
411 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
413 /* Check the SAI Block Frame parameters */
414 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
415 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
416 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
417 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
418 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
420 /* Check the SAI Block Slot parameters */
421 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
422 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
423 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
424 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
426 /* Check the SAI PDM parameters */
427 assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
428 if (hsai->Init.PdmInit.Activation == ENABLE)
430 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
431 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
432 /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
433 #if defined(SAI4)
434 if (((hsai->Instance != SAI1_Block_A) && (hsai->Instance != SAI4_Block_A)) ||
435 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
436 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
438 return HAL_ERROR;
440 #else
441 if ((hsai->Instance != SAI1_Block_A) ||
442 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
443 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
445 return HAL_ERROR;
447 #endif /* SAI4 */
450 /* Get the SAI base address according to the SAI handle */
451 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
453 SaiBaseAddress = SAI1;
455 #if defined(SAI2)
456 else if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
458 SaiBaseAddress = SAI2;
460 #endif /* SAI2 */
461 #if defined(SAI3)
462 else if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
464 SaiBaseAddress = SAI3;
466 #endif /* SAI3 */
467 #if defined(SAI4)
468 else if ((hsai->Instance == SAI4_Block_A) || (hsai->Instance == SAI4_Block_B))
470 SaiBaseAddress = SAI4;
472 #endif /* SAI4 */
473 else
475 return HAL_ERROR;
478 if (hsai->State == HAL_SAI_STATE_RESET)
480 /* Allocate lock resource and initialize it */
481 hsai->Lock = HAL_UNLOCKED;
483 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
484 /* Reset callback pointers to the weak predefined callbacks */
485 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
486 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
487 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
488 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
489 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
491 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
492 if (hsai->MspInitCallback == NULL)
494 hsai->MspInitCallback = HAL_SAI_MspInit;
496 hsai->MspInitCallback(hsai);
497 #else
498 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
499 HAL_SAI_MspInit(hsai);
500 #endif
503 /* Disable the selected SAI peripheral */
504 if(SAI_Disable(hsai) != HAL_OK)
506 return HAL_ERROR;
509 hsai->State = HAL_SAI_STATE_BUSY;
511 /* SAI Block Synchro Configuration -----------------------------------------*/
512 /* This setting must be done with both audio block (A & B) disabled */
513 switch (hsai->Init.SynchroExt)
515 case SAI_SYNCEXT_DISABLE :
516 tmpregisterGCR = 0;
517 break;
518 case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
519 tmpregisterGCR = SAI_GCR_SYNCOUT_0;
520 break;
521 case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
522 tmpregisterGCR = SAI_GCR_SYNCOUT_1;
523 break;
524 default:
525 tmpregisterGCR = 0;
526 break;
529 switch (hsai->Init.Synchro)
531 case SAI_ASYNCHRONOUS :
532 syncen_bits = 0;
533 break;
534 case SAI_SYNCHRONOUS :
535 syncen_bits = SAI_xCR1_SYNCEN_0;
536 break;
537 case SAI_SYNCHRONOUS_EXT_SAI1 :
538 syncen_bits = SAI_xCR1_SYNCEN_1;
539 break;
540 #if defined(SAI2)
541 case SAI_SYNCHRONOUS_EXT_SAI2 :
542 syncen_bits = SAI_xCR1_SYNCEN_1;
543 tmpregisterGCR |= SAI_GCR_SYNCIN_0;
544 break;
545 #endif /* SAI2 */
546 #if defined(SAI3)
547 case SAI_SYNCHRONOUS_EXT_SAI3 :
548 syncen_bits = SAI_xCR1_SYNCEN_1;
549 tmpregisterGCR |= SAI_GCR_SYNCIN_1;
550 break;
551 #endif /* SAI3 */
552 #if defined(SAI4)
553 case SAI_SYNCHRONOUS_EXT_SAI4 :
554 syncen_bits = SAI_xCR1_SYNCEN_1;
555 tmpregisterGCR |= (SAI_GCR_SYNCIN_1 | SAI_GCR_SYNCIN_0);
556 break;
557 #endif /* SAI4 */
558 default:
559 syncen_bits = 0;
560 break;
563 /* Set the SAI Block Synchro Configuration */
564 SaiBaseAddress->GCR = tmpregisterGCR;
566 if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
568 uint32_t freq = 0;
569 uint32_t tmpval;
571 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
572 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
574 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
577 #if defined(SAI2)
578 #if defined(RCC_PERIPHCLK_SAI2)
579 if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
581 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
583 #else
584 if (hsai->Instance == SAI2_Block_A)
586 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A);
588 if (hsai->Instance == SAI2_Block_B)
590 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B);
592 #endif /* RCC_PERIPHCLK_SAI2 */
593 #endif /* SAI2 */
595 #if defined(SAI3)
596 if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
598 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3);
600 #endif /* SAI3 */
601 #if defined(SAI4)
602 if (hsai->Instance == SAI4_Block_A)
604 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A);
606 if (hsai->Instance == SAI4_Block_B)
608 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B);
610 #endif /* SAI4 */
612 /* Configure Master Clock Divider using the following formula :
613 - If NODIV = 1 :
614 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
615 - If NODIV = 0 :
616 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
617 if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
619 /* NODIV = 1 */
620 /* (freq x 10) to keep Significant digits */
621 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * hsai->FrameInit.FrameLength);
623 else
625 /* NODIV = 0 */
626 uint32_t tmposr;
627 tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
628 /* (freq x 10) to keep Significant digits */
629 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
631 hsai->Init.Mckdiv = tmpval / 10U;
633 /* Round result to the nearest integer */
634 if ((tmpval % 10U) > 8U)
636 hsai->Init.Mckdiv += 1U;
640 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
641 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
643 /* Transmit */
644 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
646 else
648 /* Receive */
649 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
652 /* SAI Block Configuration -------------------------------------------------*/
653 /* SAI CR1 Configuration */
654 #if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
656 if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
658 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
659 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
660 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
661 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
662 SAI_xCR1_MCKEN);
664 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
665 hsai->Init.DataSize | hsai->Init.FirstBit | \
666 ckstr_bits | syncen_bits | \
667 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
668 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
669 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
671 else /* STM32H7xx Rev.Y */
673 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
674 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
675 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
676 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR);
678 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
679 hsai->Init.DataSize | hsai->Init.FirstBit | \
680 ckstr_bits | syncen_bits | \
681 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
682 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
683 hsai->Init.MckOverSampling);
685 #else /* SAI_VER_V2_1*/
686 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
687 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
688 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
689 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
690 SAI_xCR1_MCKEN);
692 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
693 hsai->Init.DataSize | hsai->Init.FirstBit | \
694 ckstr_bits | syncen_bits | \
695 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
696 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
697 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
698 #endif /* SAI_VER_V2_X */
700 /* SAI CR2 Configuration */
701 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
702 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
704 /* SAI Frame Configuration -----------------------------------------*/
705 hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
706 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
707 hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
708 hsai->FrameInit.FSOffset |
709 hsai->FrameInit.FSDefinition |
710 hsai->FrameInit.FSPolarity |
711 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
713 /* SAI Block_x SLOT Configuration ------------------------------------------*/
714 /* This register has no meaning in AC 97 and SPDIF audio protocol */
715 hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
716 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
718 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
719 (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8);
721 /* SAI PDM Configuration ---------------------------------------------------*/
722 #if defined(SAI4)
723 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
724 #else
725 if (hsai->Instance == SAI1_Block_A)
726 #endif /* SAI4 */
728 /* Disable PDM interface */
729 SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
730 if (hsai->Init.PdmInit.Activation == ENABLE)
732 /* Configure and enable PDM interface */
733 SaiBaseAddress->PDMCR = (hsai->Init.PdmInit.ClockEnable |
734 ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
735 SaiBaseAddress->PDMCR |= SAI_PDMCR_PDMEN;
739 /* Initialize the error code */
740 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
742 /* Initialize the SAI state */
743 hsai->State = HAL_SAI_STATE_READY;
745 /* Release Lock */
746 __HAL_UNLOCK(hsai);
748 return HAL_OK;
752 * @brief DeInitialize the SAI peripheral.
753 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
754 * the configuration information for SAI module.
755 * @retval HAL status
757 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
759 SAI_TypeDef *SaiBaseAddress;
761 /* Check the SAI handle allocation */
762 if (hsai == NULL)
764 return HAL_ERROR;
767 hsai->State = HAL_SAI_STATE_BUSY;
769 /* Disabled All interrupt and clear all the flag */
770 hsai->Instance->IMR = 0;
771 hsai->Instance->CLRFR = 0xFFFFFFFFU;
773 /* Disable the SAI */
774 if (SAI_Disable(hsai) != HAL_OK)
776 /* Reset SAI state to ready */
777 hsai->State = HAL_SAI_STATE_READY;
779 /* Release Lock */
780 __HAL_UNLOCK(hsai);
782 return HAL_ERROR;
785 /* Flush the fifo */
786 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
788 /* Disable SAI PDM interface */
789 #if defined(SAI4)
790 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
791 #else
792 if (hsai->Instance == SAI1_Block_A)
793 #endif /* SAI4 */
795 /* Get the SAI base address according to the SAI handle */
796 #if defined(SAI4)
797 SaiBaseAddress = (hsai->Instance == SAI1_Block_A) ? SAI1 : SAI4;
798 #else
799 SaiBaseAddress = SAI1;
800 #endif /* SAI4 */
802 /* Reset PDM delays */
803 SaiBaseAddress->PDMDLY = 0U;
805 /* Disable PDM interface */
806 SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
809 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
810 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
811 if (hsai->MspDeInitCallback == NULL)
813 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
815 hsai->MspDeInitCallback(hsai);
816 #else
817 HAL_SAI_MspDeInit(hsai);
818 #endif
820 /* Initialize the error code */
821 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
823 /* Initialize the SAI state */
824 hsai->State = HAL_SAI_STATE_RESET;
826 /* Release Lock */
827 __HAL_UNLOCK(hsai);
829 return HAL_OK;
833 * @brief Initialize the SAI MSP.
834 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
835 * the configuration information for SAI module.
836 * @retval None
838 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
840 /* Prevent unused argument(s) compilation warning */
841 UNUSED(hsai);
843 /* NOTE : This function should not be modified, when the callback is needed,
844 the HAL_SAI_MspInit could be implemented in the user file
849 * @brief DeInitialize the SAI MSP.
850 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
851 * the configuration information for SAI module.
852 * @retval None
854 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
856 /* Prevent unused argument(s) compilation warning */
857 UNUSED(hsai);
859 /* NOTE : This function should not be modified, when the callback is needed,
860 the HAL_SAI_MspDeInit could be implemented in the user file
864 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
866 * @brief Register a user SAI callback
867 * to be used instead of the weak predefined callback.
868 * @param hsai SAI handle.
869 * @param CallbackID ID of the callback to be registered.
870 * This parameter can be one of the following values:
871 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
872 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
873 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
874 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
875 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
876 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
877 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
878 * @param pCallback pointer to the callback function.
879 * @retval HAL status.
881 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
882 HAL_SAI_CallbackIDTypeDef CallbackID,
883 pSAI_CallbackTypeDef pCallback)
885 HAL_StatusTypeDef status = HAL_OK;
887 if (pCallback == NULL)
889 /* update the error code */
890 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
891 /* update return status */
892 status = HAL_ERROR;
894 else
896 if (HAL_SAI_STATE_READY == hsai->State)
898 switch (CallbackID)
900 case HAL_SAI_RX_COMPLETE_CB_ID :
901 hsai->RxCpltCallback = pCallback;
902 break;
903 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
904 hsai->RxHalfCpltCallback = pCallback;
905 break;
906 case HAL_SAI_TX_COMPLETE_CB_ID :
907 hsai->TxCpltCallback = pCallback;
908 break;
909 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
910 hsai->TxHalfCpltCallback = pCallback;
911 break;
912 case HAL_SAI_ERROR_CB_ID :
913 hsai->ErrorCallback = pCallback;
914 break;
915 case HAL_SAI_MSPINIT_CB_ID :
916 hsai->MspInitCallback = pCallback;
917 break;
918 case HAL_SAI_MSPDEINIT_CB_ID :
919 hsai->MspDeInitCallback = pCallback;
920 break;
921 default :
922 /* update the error code */
923 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
924 /* update return status */
925 status = HAL_ERROR;
926 break;
929 else if (HAL_SAI_STATE_RESET == hsai->State)
931 switch (CallbackID)
933 case HAL_SAI_MSPINIT_CB_ID :
934 hsai->MspInitCallback = pCallback;
935 break;
936 case HAL_SAI_MSPDEINIT_CB_ID :
937 hsai->MspDeInitCallback = pCallback;
938 break;
939 default :
940 /* update the error code */
941 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
942 /* update return status */
943 status = HAL_ERROR;
944 break;
947 else
949 /* update the error code */
950 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
951 /* update return status */
952 status = HAL_ERROR;
955 return status;
959 * @brief Unregister a user SAI callback.
960 * SAI callback is redirected to the weak predefined callback.
961 * @param hsai SAI handle.
962 * @param CallbackID ID of the callback to be unregistered.
963 * This parameter can be one of the following values:
964 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
965 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
966 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
967 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
968 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
969 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
970 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
971 * @retval HAL status.
973 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
974 HAL_SAI_CallbackIDTypeDef CallbackID)
976 HAL_StatusTypeDef status = HAL_OK;
978 if (HAL_SAI_STATE_READY == hsai->State)
980 switch (CallbackID)
982 case HAL_SAI_RX_COMPLETE_CB_ID :
983 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
984 break;
985 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
986 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
987 break;
988 case HAL_SAI_TX_COMPLETE_CB_ID :
989 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
990 break;
991 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
992 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
993 break;
994 case HAL_SAI_ERROR_CB_ID :
995 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
996 break;
997 case HAL_SAI_MSPINIT_CB_ID :
998 hsai->MspInitCallback = HAL_SAI_MspInit;
999 break;
1000 case HAL_SAI_MSPDEINIT_CB_ID :
1001 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1002 break;
1003 default :
1004 /* update the error code */
1005 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1006 /* update return status */
1007 status = HAL_ERROR;
1008 break;
1011 else if (HAL_SAI_STATE_RESET == hsai->State)
1013 switch (CallbackID)
1015 case HAL_SAI_MSPINIT_CB_ID :
1016 hsai->MspInitCallback = HAL_SAI_MspInit;
1017 break;
1018 case HAL_SAI_MSPDEINIT_CB_ID :
1019 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1020 break;
1021 default :
1022 /* update the error code */
1023 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1024 /* update return status */
1025 status = HAL_ERROR;
1026 break;
1029 else
1031 /* update the error code */
1032 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1033 /* update return status */
1034 status = HAL_ERROR;
1036 return status;
1038 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1041 * @}
1044 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
1045 * @brief Data transfers functions
1047 @verbatim
1048 ==============================================================================
1049 ##### IO operation functions #####
1050 ==============================================================================
1051 [..]
1052 This subsection provides a set of functions allowing to manage the SAI data
1053 transfers.
1055 (+) There are two modes of transfer:
1056 (++) Blocking mode : The communication is performed in the polling mode.
1057 The status of all data processing is returned by the same function
1058 after finishing transfer.
1059 (++) No-Blocking mode : The communication is performed using Interrupts
1060 or DMA. These functions return the status of the transfer startup.
1061 The end of the data processing will be indicated through the
1062 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
1063 using DMA mode.
1065 (+) Blocking mode functions are :
1066 (++) HAL_SAI_Transmit()
1067 (++) HAL_SAI_Receive()
1069 (+) Non Blocking mode functions with Interrupt are :
1070 (++) HAL_SAI_Transmit_IT()
1071 (++) HAL_SAI_Receive_IT()
1073 (+) Non Blocking mode functions with DMA are :
1074 (++) HAL_SAI_Transmit_DMA()
1075 (++) HAL_SAI_Receive_DMA()
1077 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1078 (++) HAL_SAI_TxCpltCallback()
1079 (++) HAL_SAI_RxCpltCallback()
1080 (++) HAL_SAI_ErrorCallback()
1082 @endverbatim
1083 * @{
1087 * @brief Transmit an amount of data in blocking mode.
1088 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1089 * the configuration information for SAI module.
1090 * @param pData Pointer to data buffer
1091 * @param Size Amount of data to be sent
1092 * @param Timeout Timeout duration
1093 * @retval HAL status
1095 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1097 uint32_t tickstart = HAL_GetTick();
1098 uint32_t temp;
1100 if ((pData == NULL) || (Size == 0U))
1102 return HAL_ERROR;
1105 if (hsai->State == HAL_SAI_STATE_READY)
1107 /* Process Locked */
1108 __HAL_LOCK(hsai);
1110 hsai->XferSize = Size;
1111 hsai->XferCount = Size;
1112 hsai->pBuffPtr = pData;
1113 hsai->State = HAL_SAI_STATE_BUSY_TX;
1114 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1116 /* Check if the SAI is already enabled */
1117 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1119 /* fill the fifo with data before to enabled the SAI */
1120 SAI_FillFifo(hsai);
1121 /* Enable SAI peripheral */
1122 __HAL_SAI_ENABLE(hsai);
1125 while (hsai->XferCount > 0U)
1127 /* Write data if the FIFO is not full */
1128 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
1130 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1132 hsai->Instance->DR = *hsai->pBuffPtr;
1133 hsai->pBuffPtr++;
1135 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1137 temp = (uint32_t)(*hsai->pBuffPtr);
1138 hsai->pBuffPtr++;
1139 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1140 hsai->pBuffPtr++;
1141 hsai->Instance->DR = temp;
1143 else
1145 temp = (uint32_t)(*hsai->pBuffPtr);
1146 hsai->pBuffPtr++;
1147 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1148 hsai->pBuffPtr++;
1149 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
1150 hsai->pBuffPtr++;
1151 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
1152 hsai->pBuffPtr++;
1153 hsai->Instance->DR = temp;
1155 hsai->XferCount--;
1157 else
1159 /* Check for the Timeout */
1160 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1162 /* Update error code */
1163 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1165 /* Clear all the flags */
1166 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1168 /* Disable SAI peripheral */
1169 /* No need to check return value because state update, unlock and error return will be performed later */
1170 (void) SAI_Disable(hsai);
1172 /* Flush the fifo */
1173 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1175 /* Change the SAI state */
1176 hsai->State = HAL_SAI_STATE_READY;
1178 /* Process Unlocked */
1179 __HAL_UNLOCK(hsai);
1181 return HAL_ERROR;
1186 hsai->State = HAL_SAI_STATE_READY;
1188 /* Process Unlocked */
1189 __HAL_UNLOCK(hsai);
1191 return HAL_OK;
1193 else
1195 return HAL_BUSY;
1200 * @brief Receive an amount of data in blocking mode.
1201 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1202 * the configuration information for SAI module.
1203 * @param pData Pointer to data buffer
1204 * @param Size Amount of data to be received
1205 * @param Timeout Timeout duration
1206 * @retval HAL status
1208 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1210 uint32_t tickstart = HAL_GetTick();
1211 uint32_t temp;
1213 if ((pData == NULL) || (Size == 0U))
1215 return HAL_ERROR;
1218 if (hsai->State == HAL_SAI_STATE_READY)
1220 /* Process Locked */
1221 __HAL_LOCK(hsai);
1223 hsai->pBuffPtr = pData;
1224 hsai->XferSize = Size;
1225 hsai->XferCount = Size;
1226 hsai->State = HAL_SAI_STATE_BUSY_RX;
1227 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1229 /* Check if the SAI is already enabled */
1230 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1232 /* Enable SAI peripheral */
1233 __HAL_SAI_ENABLE(hsai);
1236 /* Receive data */
1237 while (hsai->XferCount > 0U)
1239 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1241 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1243 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
1244 hsai->pBuffPtr++;
1246 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1248 temp = hsai->Instance->DR;
1249 *hsai->pBuffPtr = (uint8_t)temp;
1250 hsai->pBuffPtr++;
1251 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1252 hsai->pBuffPtr++;
1254 else
1256 temp = hsai->Instance->DR;
1257 *hsai->pBuffPtr = (uint8_t)temp;
1258 hsai->pBuffPtr++;
1259 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1260 hsai->pBuffPtr++;
1261 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
1262 hsai->pBuffPtr++;
1263 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
1264 hsai->pBuffPtr++;
1266 hsai->XferCount--;
1268 else
1270 /* Check for the Timeout */
1271 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1273 /* Update error code */
1274 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1276 /* Clear all the flags */
1277 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1279 /* Disable SAI peripheral */
1280 /* No need to check return value because state update, unlock and error return will be performed later */
1281 (void) SAI_Disable(hsai);
1283 /* Flush the fifo */
1284 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1286 /* Change the SAI state */
1287 hsai->State = HAL_SAI_STATE_READY;
1289 /* Process Unlocked */
1290 __HAL_UNLOCK(hsai);
1292 return HAL_ERROR;
1297 hsai->State = HAL_SAI_STATE_READY;
1299 /* Process Unlocked */
1300 __HAL_UNLOCK(hsai);
1302 return HAL_OK;
1304 else
1306 return HAL_BUSY;
1311 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1312 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1313 * the configuration information for SAI module.
1314 * @param pData Pointer to data buffer
1315 * @param Size Amount of data to be sent
1316 * @retval HAL status
1318 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1320 if ((pData == NULL) || (Size == 0U))
1322 return HAL_ERROR;
1325 if (hsai->State == HAL_SAI_STATE_READY)
1327 /* Process Locked */
1328 __HAL_LOCK(hsai);
1330 hsai->pBuffPtr = pData;
1331 hsai->XferSize = Size;
1332 hsai->XferCount = Size;
1333 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1334 hsai->State = HAL_SAI_STATE_BUSY_TX;
1336 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1338 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1340 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1342 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1344 else
1346 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1349 /* Fill the fifo before starting the communication */
1350 SAI_FillFifo(hsai);
1352 /* Enable FRQ and OVRUDR interrupts */
1353 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1355 /* Check if the SAI is already enabled */
1356 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1358 /* Enable SAI peripheral */
1359 __HAL_SAI_ENABLE(hsai);
1361 /* Process Unlocked */
1362 __HAL_UNLOCK(hsai);
1364 return HAL_OK;
1366 else
1368 return HAL_BUSY;
1373 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1374 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1375 * the configuration information for SAI module.
1376 * @param pData Pointer to data buffer
1377 * @param Size Amount of data to be received
1378 * @retval HAL status
1380 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1382 if ((pData == NULL) || (Size == 0U))
1384 return HAL_ERROR;
1387 if (hsai->State == HAL_SAI_STATE_READY)
1389 /* Process Locked */
1390 __HAL_LOCK(hsai);
1392 hsai->pBuffPtr = pData;
1393 hsai->XferSize = Size;
1394 hsai->XferCount = Size;
1395 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1396 hsai->State = HAL_SAI_STATE_BUSY_RX;
1398 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1400 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1402 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1404 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1406 else
1408 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1411 /* Enable TXE and OVRUDR interrupts */
1412 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1414 /* Check if the SAI is already enabled */
1415 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1417 /* Enable SAI peripheral */
1418 __HAL_SAI_ENABLE(hsai);
1421 /* Process Unlocked */
1422 __HAL_UNLOCK(hsai);
1424 return HAL_OK;
1426 else
1428 return HAL_BUSY;
1433 * @brief Pause the audio stream playing from the Media.
1434 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1435 * the configuration information for SAI module.
1436 * @retval HAL status
1438 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1440 /* Process Locked */
1441 __HAL_LOCK(hsai);
1443 /* Pause the audio file playing by disabling the SAI DMA requests */
1444 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1446 /* Process Unlocked */
1447 __HAL_UNLOCK(hsai);
1449 return HAL_OK;
1453 * @brief Resume the audio stream playing from the Media.
1454 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1455 * the configuration information for SAI module.
1456 * @retval HAL status
1458 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1460 /* Process Locked */
1461 __HAL_LOCK(hsai);
1463 /* Enable the SAI DMA requests */
1464 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1466 /* If the SAI peripheral is still not enabled, enable it */
1467 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1469 /* Enable SAI peripheral */
1470 __HAL_SAI_ENABLE(hsai);
1473 /* Process Unlocked */
1474 __HAL_UNLOCK(hsai);
1476 return HAL_OK;
1480 * @brief Stop the audio stream playing from the Media.
1481 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1482 * the configuration information for SAI module.
1483 * @retval HAL status
1485 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1487 HAL_StatusTypeDef status = HAL_OK;
1489 /* Process Locked */
1490 __HAL_LOCK(hsai);
1492 /* Disable the SAI DMA request */
1493 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1495 /* Abort the SAI Tx DMA Stream */
1496 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1498 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1500 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1501 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1503 status = HAL_ERROR;
1504 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1509 /* Abort the SAI Rx DMA Stream */
1510 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1512 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1514 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1515 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1517 status = HAL_ERROR;
1518 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1523 /* Disable SAI peripheral */
1524 if (SAI_Disable(hsai) != HAL_OK)
1526 status = HAL_ERROR;
1529 /* Flush the fifo */
1530 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1532 /* Set hsai state to ready */
1533 hsai->State = HAL_SAI_STATE_READY;
1535 /* Process Unlocked */
1536 __HAL_UNLOCK(hsai);
1538 return status;
1542 * @brief Abort the current transfer and disable the SAI.
1543 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1544 * the configuration information for SAI module.
1545 * @retval HAL status
1547 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1549 HAL_StatusTypeDef status = HAL_OK;
1551 /* Process Locked */
1552 __HAL_LOCK(hsai);
1554 /* Check SAI DMA is enabled or not */
1555 if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1557 /* Disable the SAI DMA request */
1558 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1560 /* Abort the SAI Tx DMA Stream */
1561 if ((hsai->State == HAL_SAI_STATE_BUSY_TX)&& (hsai->hdmatx != NULL))
1563 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1565 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1566 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1568 status = HAL_ERROR;
1569 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1574 /* Abort the SAI Rx DMA Stream */
1575 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1577 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1579 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1580 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1582 status = HAL_ERROR;
1583 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1589 /* Disabled All interrupt and clear all the flag */
1590 hsai->Instance->IMR = 0;
1591 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1593 /* Disable SAI peripheral */
1594 if (SAI_Disable(hsai) != HAL_OK)
1596 status = HAL_ERROR;
1599 /* Flush the fifo */
1600 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1602 /* Set hsai state to ready */
1603 hsai->State = HAL_SAI_STATE_READY;
1605 /* Process Unlocked */
1606 __HAL_UNLOCK(hsai);
1608 return status;
1612 * @brief Transmit an amount of data in non-blocking mode with DMA.
1613 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1614 * the configuration information for SAI module.
1615 * @param pData Pointer to data buffer
1616 * @param Size Amount of data to be sent
1617 * @retval HAL status
1619 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1621 uint32_t tickstart = HAL_GetTick();
1623 if ((pData == NULL) || (Size == 0U))
1625 return HAL_ERROR;
1628 if (hsai->State == HAL_SAI_STATE_READY)
1630 /* Process Locked */
1631 __HAL_LOCK(hsai);
1633 hsai->pBuffPtr = pData;
1634 hsai->XferSize = Size;
1635 hsai->XferCount = Size;
1636 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1637 hsai->State = HAL_SAI_STATE_BUSY_TX;
1639 /* Set the SAI Tx DMA Half transfer complete callback */
1640 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1642 /* Set the SAI TxDMA transfer complete callback */
1643 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1645 /* Set the DMA error callback */
1646 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1648 /* Set the DMA Tx abort callback */
1649 hsai->hdmatx->XferAbortCallback = NULL;
1651 /* Enable the Tx DMA Stream */
1652 if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1654 __HAL_UNLOCK(hsai);
1655 return HAL_ERROR;
1658 /* Enable the interrupts for error handling */
1659 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1661 /* Enable SAI Tx DMA Request */
1662 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1664 /* Wait untill FIFO is not empty */
1665 while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1667 /* Check for the Timeout */
1668 if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1670 /* Update error code */
1671 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1673 /* Process Unlocked */
1674 __HAL_UNLOCK(hsai);
1676 return HAL_TIMEOUT;
1680 /* Check if the SAI is already enabled */
1681 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1683 /* Enable SAI peripheral */
1684 __HAL_SAI_ENABLE(hsai);
1687 /* Process Unlocked */
1688 __HAL_UNLOCK(hsai);
1690 return HAL_OK;
1692 else
1694 return HAL_BUSY;
1699 * @brief Receive an amount of data in non-blocking mode with DMA.
1700 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1701 * the configuration information for SAI module.
1702 * @param pData Pointer to data buffer
1703 * @param Size Amount of data to be received
1704 * @retval HAL status
1706 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1709 if ((pData == NULL) || (Size == 0U))
1711 return HAL_ERROR;
1714 if (hsai->State == HAL_SAI_STATE_READY)
1716 /* Process Locked */
1717 __HAL_LOCK(hsai);
1719 hsai->pBuffPtr = pData;
1720 hsai->XferSize = Size;
1721 hsai->XferCount = Size;
1722 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1723 hsai->State = HAL_SAI_STATE_BUSY_RX;
1725 /* Set the SAI Rx DMA Half transfer complete callback */
1726 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1728 /* Set the SAI Rx DMA transfer complete callback */
1729 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1731 /* Set the DMA error callback */
1732 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1734 /* Set the DMA Rx abort callback */
1735 hsai->hdmarx->XferAbortCallback = NULL;
1737 /* Enable the Rx DMA Stream */
1738 if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1740 __HAL_UNLOCK(hsai);
1741 return HAL_ERROR;
1744 /* Enable the interrupts for error handling */
1745 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1747 /* Enable SAI Rx DMA Request */
1748 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1750 /* Check if the SAI is already enabled */
1751 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1753 /* Enable SAI peripheral */
1754 __HAL_SAI_ENABLE(hsai);
1757 /* Process Unlocked */
1758 __HAL_UNLOCK(hsai);
1760 return HAL_OK;
1762 else
1764 return HAL_BUSY;
1769 * @brief Enable the Tx mute mode.
1770 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1771 * the configuration information for SAI module.
1772 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1773 * @retval HAL status
1775 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1777 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1779 if (hsai->State != HAL_SAI_STATE_RESET)
1781 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1782 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
1783 return HAL_OK;
1785 return HAL_ERROR;
1789 * @brief Disable the Tx mute mode.
1790 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1791 * the configuration information for SAI module.
1792 * @retval HAL status
1794 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1796 if (hsai->State != HAL_SAI_STATE_RESET)
1798 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1799 return HAL_OK;
1801 return HAL_ERROR;
1805 * @brief Enable the Rx mute detection.
1806 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1807 * the configuration information for SAI module.
1808 * @param callback function called when the mute is detected.
1809 * @param counter number a data before mute detection max 63.
1810 * @retval HAL status
1812 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1814 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1816 if (hsai->State != HAL_SAI_STATE_RESET)
1818 /* set the mute counter */
1819 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1820 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1821 hsai->mutecallback = callback;
1822 /* enable the IT interrupt */
1823 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1824 return HAL_OK;
1826 return HAL_ERROR;
1830 * @brief Disable the Rx mute detection.
1831 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1832 * the configuration information for SAI module.
1833 * @retval HAL status
1835 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1837 if (hsai->State != HAL_SAI_STATE_RESET)
1839 /* set the mutecallback to NULL */
1840 hsai->mutecallback = NULL;
1841 /* enable the IT interrupt */
1842 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1843 return HAL_OK;
1845 return HAL_ERROR;
1849 * @brief Handle SAI interrupt request.
1850 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1851 * the configuration information for SAI module.
1852 * @retval None
1854 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1856 if (hsai->State != HAL_SAI_STATE_RESET)
1858 uint32_t itflags = hsai->Instance->SR;
1859 uint32_t itsources = hsai->Instance->IMR;
1860 uint32_t cr1config = hsai->Instance->CR1;
1861 uint32_t tmperror;
1863 /* SAI Fifo request interrupt occured ------------------------------------*/
1864 if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1866 hsai->InterruptServiceRoutine(hsai);
1868 /* SAI Overrun error interrupt occurred ----------------------------------*/
1869 else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1871 /* Clear the SAI Overrun flag */
1872 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1873 /* Get the SAI error code */
1874 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1875 /* Change the SAI error code */
1876 hsai->ErrorCode |= tmperror;
1877 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1878 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1879 hsai->ErrorCallback(hsai);
1880 #else
1881 HAL_SAI_ErrorCallback(hsai);
1882 #endif
1884 /* SAI mutedet interrupt occurred ----------------------------------*/
1885 else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1887 /* Clear the SAI mutedet flag */
1888 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1889 /* call the call back function */
1890 if (hsai->mutecallback != NULL)
1892 /* inform the user that an RX mute event has been detected */
1893 hsai->mutecallback();
1896 /* SAI AFSDET interrupt occurred ----------------------------------*/
1897 else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1899 /* Clear the SAI AFSDET flag */
1900 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1902 /* Change the SAI error code */
1903 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1905 /* Check SAI DMA is enabled or not */
1906 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1908 /* Abort the SAI DMA Streams */
1909 if (hsai->hdmatx != NULL)
1911 /* Set the DMA Tx abort callback */
1912 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1914 /* Abort DMA in IT mode */
1915 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1917 /* Update SAI error code */
1918 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1920 /* Call SAI error callback */
1921 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1922 hsai->ErrorCallback(hsai);
1923 #else
1924 HAL_SAI_ErrorCallback(hsai);
1925 #endif
1928 if (hsai->hdmarx != NULL)
1930 /* Set the DMA Rx abort callback */
1931 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1933 /* Abort DMA in IT mode */
1934 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1936 /* Update SAI error code */
1937 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1939 /* Call SAI error callback */
1940 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1941 hsai->ErrorCallback(hsai);
1942 #else
1943 HAL_SAI_ErrorCallback(hsai);
1944 #endif
1948 else
1950 /* Abort SAI */
1951 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1952 (void) HAL_SAI_Abort(hsai);
1954 /* Set error callback */
1955 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1956 hsai->ErrorCallback(hsai);
1957 #else
1958 HAL_SAI_ErrorCallback(hsai);
1959 #endif
1962 /* SAI LFSDET interrupt occurred ----------------------------------*/
1963 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1965 /* Clear the SAI LFSDET flag */
1966 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1968 /* Change the SAI error code */
1969 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1971 /* Check SAI DMA is enabled or not */
1972 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1974 /* Abort the SAI DMA Streams */
1975 if (hsai->hdmatx != NULL)
1977 /* Set the DMA Tx abort callback */
1978 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1980 /* Abort DMA in IT mode */
1981 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1983 /* Update SAI error code */
1984 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1986 /* Call SAI error callback */
1987 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1988 hsai->ErrorCallback(hsai);
1989 #else
1990 HAL_SAI_ErrorCallback(hsai);
1991 #endif
1994 if (hsai->hdmarx != NULL)
1996 /* Set the DMA Rx abort callback */
1997 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1999 /* Abort DMA in IT mode */
2000 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2002 /* Update SAI error code */
2003 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2005 /* Call SAI error callback */
2006 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2007 hsai->ErrorCallback(hsai);
2008 #else
2009 HAL_SAI_ErrorCallback(hsai);
2010 #endif
2014 else
2016 /* Abort SAI */
2017 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
2018 (void) HAL_SAI_Abort(hsai);
2020 /* Set error callback */
2021 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2022 hsai->ErrorCallback(hsai);
2023 #else
2024 HAL_SAI_ErrorCallback(hsai);
2025 #endif
2028 /* SAI WCKCFG interrupt occurred ----------------------------------*/
2029 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
2031 /* Clear the SAI WCKCFG flag */
2032 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
2034 /* Change the SAI error code */
2035 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
2037 /* Check SAI DMA is enabled or not */
2038 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
2040 /* Abort the SAI DMA Streams */
2041 if (hsai->hdmatx != NULL)
2043 /* Set the DMA Tx abort callback */
2044 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
2046 /* Abort DMA in IT mode */
2047 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
2049 /* Update SAI error code */
2050 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2052 /* Call SAI error callback */
2053 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2054 hsai->ErrorCallback(hsai);
2055 #else
2056 HAL_SAI_ErrorCallback(hsai);
2057 #endif
2060 if (hsai->hdmarx != NULL)
2062 /* Set the DMA Rx abort callback */
2063 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
2065 /* Abort DMA in IT mode */
2066 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2068 /* Update SAI error code */
2069 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2071 /* Call SAI error callback */
2072 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2073 hsai->ErrorCallback(hsai);
2074 #else
2075 HAL_SAI_ErrorCallback(hsai);
2076 #endif
2080 else
2082 /* If WCKCFG occurs, SAI audio block is automatically disabled */
2083 /* Disable all interrupts and clear all flags */
2084 hsai->Instance->IMR = 0U;
2085 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2086 /* Set the SAI state to ready to be able to start again the process */
2087 hsai->State = HAL_SAI_STATE_READY;
2089 /* Initialize XferCount */
2090 hsai->XferCount = 0U;
2092 /* SAI error Callback */
2093 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2094 hsai->ErrorCallback(hsai);
2095 #else
2096 HAL_SAI_ErrorCallback(hsai);
2097 #endif
2100 /* SAI CNRDY interrupt occurred ----------------------------------*/
2101 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
2103 /* Clear the SAI CNRDY flag */
2104 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
2105 /* Change the SAI error code */
2106 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
2107 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
2108 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2109 hsai->ErrorCallback(hsai);
2110 #else
2111 HAL_SAI_ErrorCallback(hsai);
2112 #endif
2114 else
2116 /* Nothing to do */
2122 * @brief Tx Transfer completed callback.
2123 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2124 * the configuration information for SAI module.
2125 * @retval None
2127 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
2129 /* Prevent unused argument(s) compilation warning */
2130 UNUSED(hsai);
2132 /* NOTE : This function should not be modified, when the callback is needed,
2133 the HAL_SAI_TxCpltCallback could be implemented in the user file
2138 * @brief Tx Transfer Half completed callback.
2139 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2140 * the configuration information for SAI module.
2141 * @retval None
2143 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2145 /* Prevent unused argument(s) compilation warning */
2146 UNUSED(hsai);
2148 /* NOTE : This function should not be modified, when the callback is needed,
2149 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2154 * @brief Rx Transfer completed callback.
2155 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2156 * the configuration information for SAI module.
2157 * @retval None
2159 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
2161 /* Prevent unused argument(s) compilation warning */
2162 UNUSED(hsai);
2164 /* NOTE : This function should not be modified, when the callback is needed,
2165 the HAL_SAI_RxCpltCallback could be implemented in the user file
2170 * @brief Rx Transfer half completed callback.
2171 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2172 * the configuration information for SAI module.
2173 * @retval None
2175 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2177 /* Prevent unused argument(s) compilation warning */
2178 UNUSED(hsai);
2180 /* NOTE : This function should not be modified, when the callback is needed,
2181 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2186 * @brief SAI error callback.
2187 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2188 * the configuration information for SAI module.
2189 * @retval None
2191 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
2193 /* Prevent unused argument(s) compilation warning */
2194 UNUSED(hsai);
2196 /* NOTE : This function should not be modified, when the callback is needed,
2197 the HAL_SAI_ErrorCallback could be implemented in the user file
2202 * @}
2205 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2206 * @brief Peripheral State functions
2208 @verbatim
2209 ===============================================================================
2210 ##### Peripheral State and Errors functions #####
2211 ===============================================================================
2212 [..]
2213 This subsection permits to get in run-time the status of the peripheral
2214 and the data flow.
2216 @endverbatim
2217 * @{
2221 * @brief Return the SAI handle state.
2222 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2223 * the configuration information for SAI module.
2224 * @retval HAL state
2226 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
2228 return hsai->State;
2232 * @brief Return the SAI error code.
2233 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2234 * the configuration information for the specified SAI Block.
2235 * @retval SAI Error Code
2237 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
2239 return hsai->ErrorCode;
2243 * @}
2247 * @}
2250 /** @addtogroup SAI_Private_Functions
2251 * @brief Private functions
2252 * @{
2256 * @brief Initialize the SAI I2S protocol according to the specified parameters
2257 * in the SAI_InitTypeDef and create the associated handle.
2258 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2259 * the configuration information for SAI module.
2260 * @param protocol one of the supported protocol.
2261 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2262 * @param nbslot number of slot minimum value is 2 and max is 16.
2263 * the value must be a multiple of 2.
2264 * @retval HAL status
2266 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2268 HAL_StatusTypeDef status = HAL_OK;
2270 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2271 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2272 /* Compute ClockStrobing according AudioMode */
2273 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2275 /* Transmit */
2276 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2278 else
2280 /* Receive */
2281 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2283 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
2284 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2285 hsai->SlotInit.FirstBitOffset = 0;
2286 hsai->SlotInit.SlotNumber = nbslot;
2288 /* in IS2 the number of slot must be even */
2289 if ((nbslot & 0x1U) != 0U)
2291 return HAL_ERROR;
2294 if (protocol == SAI_I2S_STANDARD)
2296 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2297 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2299 else
2301 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2302 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2303 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
2306 /* Frame definition */
2307 switch (datasize)
2309 case SAI_PROTOCOL_DATASIZE_16BIT:
2310 hsai->Init.DataSize = SAI_DATASIZE_16;
2311 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2312 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2313 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2314 break;
2315 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2316 hsai->Init.DataSize = SAI_DATASIZE_16;
2317 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2318 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2319 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2320 break;
2321 case SAI_PROTOCOL_DATASIZE_24BIT:
2322 hsai->Init.DataSize = SAI_DATASIZE_24;
2323 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2324 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2325 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2326 break;
2327 case SAI_PROTOCOL_DATASIZE_32BIT:
2328 hsai->Init.DataSize = SAI_DATASIZE_32;
2329 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2330 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2331 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2332 break;
2333 default :
2334 status = HAL_ERROR;
2335 break;
2337 if (protocol == SAI_I2S_LSBJUSTIFIED)
2339 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2341 hsai->SlotInit.FirstBitOffset = 16;
2343 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2345 hsai->SlotInit.FirstBitOffset = 8;
2348 return status;
2352 * @brief Initialize the SAI PCM protocol according to the specified parameters
2353 * in the SAI_InitTypeDef and create the associated handle.
2354 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2355 * the configuration information for SAI module.
2356 * @param protocol one of the supported protocol
2357 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2358 * @param nbslot number of slot minimum value is 1 and the max is 16.
2359 * @retval HAL status
2361 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2363 HAL_StatusTypeDef status = HAL_OK;
2365 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2366 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2367 /* Compute ClockStrobing according AudioMode */
2368 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2370 /* Transmit */
2371 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2373 else
2375 /* Receive */
2376 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2378 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2379 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2380 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2381 hsai->SlotInit.FirstBitOffset = 0;
2382 hsai->SlotInit.SlotNumber = nbslot;
2383 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2385 if (protocol == SAI_PCM_SHORT)
2387 hsai->FrameInit.ActiveFrameLength = 1;
2389 else
2391 /* SAI_PCM_LONG */
2392 hsai->FrameInit.ActiveFrameLength = 13;
2395 switch (datasize)
2397 case SAI_PROTOCOL_DATASIZE_16BIT:
2398 hsai->Init.DataSize = SAI_DATASIZE_16;
2399 hsai->FrameInit.FrameLength = 16U * nbslot;
2400 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2401 break;
2402 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2403 hsai->Init.DataSize = SAI_DATASIZE_16;
2404 hsai->FrameInit.FrameLength = 32U * nbslot;
2405 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2406 break;
2407 case SAI_PROTOCOL_DATASIZE_24BIT :
2408 hsai->Init.DataSize = SAI_DATASIZE_24;
2409 hsai->FrameInit.FrameLength = 32U * nbslot;
2410 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2411 break;
2412 case SAI_PROTOCOL_DATASIZE_32BIT:
2413 hsai->Init.DataSize = SAI_DATASIZE_32;
2414 hsai->FrameInit.FrameLength = 32U * nbslot;
2415 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2416 break;
2417 default :
2418 status = HAL_ERROR;
2419 break;
2422 return status;
2426 * @brief Fill the fifo.
2427 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2428 * the configuration information for SAI module.
2429 * @retval None
2431 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2433 uint32_t temp;
2435 /* fill the fifo with data before to enabled the SAI */
2436 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2438 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2440 hsai->Instance->DR = *hsai->pBuffPtr;
2441 hsai->pBuffPtr++;
2443 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2445 temp = (uint32_t)(*hsai->pBuffPtr);
2446 hsai->pBuffPtr++;
2447 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2448 hsai->pBuffPtr++;
2449 hsai->Instance->DR = temp;
2451 else
2453 temp = (uint32_t)(*hsai->pBuffPtr);
2454 hsai->pBuffPtr++;
2455 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2456 hsai->pBuffPtr++;
2457 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2458 hsai->pBuffPtr++;
2459 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2460 hsai->pBuffPtr++;
2461 hsai->Instance->DR = temp;
2463 hsai->XferCount--;
2468 * @brief Return the interrupt flag to set according the SAI setup.
2469 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2470 * the configuration information for SAI module.
2471 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2472 * @retval the list of the IT flag to enable
2474 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
2476 uint32_t tmpIT = SAI_IT_OVRUDR;
2478 if (mode == SAI_MODE_IT)
2480 tmpIT |= SAI_IT_FREQ;
2483 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2484 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2486 tmpIT |= SAI_IT_CNRDY;
2489 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2491 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2493 else
2495 /* hsai has been configured in master mode */
2496 tmpIT |= SAI_IT_WCKCFG;
2498 return tmpIT;
2502 * @brief Disable the SAI and wait for the disabling.
2503 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2504 * the configuration information for SAI module.
2505 * @retval None
2507 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2509 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2510 HAL_StatusTypeDef status = HAL_OK;
2512 /* Disable the SAI instance */
2513 __HAL_SAI_DISABLE(hsai);
2517 /* Check for the Timeout */
2518 if (count == 0U)
2520 /* Update error code */
2521 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2522 status = HAL_TIMEOUT;
2523 break;
2525 count--;
2527 while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
2529 return status;
2533 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2534 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2535 * the configuration information for SAI module.
2536 * @retval None
2538 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2540 if (hsai->XferCount == 0U)
2542 /* Handle the end of the transmission */
2543 /* Disable FREQ and OVRUDR interrupts */
2544 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2545 hsai->State = HAL_SAI_STATE_READY;
2546 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2547 hsai->TxCpltCallback(hsai);
2548 #else
2549 HAL_SAI_TxCpltCallback(hsai);
2550 #endif
2552 else
2554 /* Write data on DR register */
2555 hsai->Instance->DR = *hsai->pBuffPtr;
2556 hsai->pBuffPtr++;
2557 hsai->XferCount--;
2562 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2563 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2564 * the configuration information for SAI module.
2565 * @retval None
2567 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2569 if (hsai->XferCount == 0U)
2571 /* Handle the end of the transmission */
2572 /* Disable FREQ and OVRUDR interrupts */
2573 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2574 hsai->State = HAL_SAI_STATE_READY;
2575 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2576 hsai->TxCpltCallback(hsai);
2577 #else
2578 HAL_SAI_TxCpltCallback(hsai);
2579 #endif
2581 else
2583 /* Write data on DR register */
2584 uint32_t temp;
2585 temp = (uint32_t)(*hsai->pBuffPtr);
2586 hsai->pBuffPtr++;
2587 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2588 hsai->pBuffPtr++;
2589 hsai->Instance->DR = temp;
2590 hsai->XferCount--;
2595 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2596 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2597 * the configuration information for SAI module.
2598 * @retval None
2600 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2602 if (hsai->XferCount == 0U)
2604 /* Handle the end of the transmission */
2605 /* Disable FREQ and OVRUDR interrupts */
2606 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2607 hsai->State = HAL_SAI_STATE_READY;
2608 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2609 hsai->TxCpltCallback(hsai);
2610 #else
2611 HAL_SAI_TxCpltCallback(hsai);
2612 #endif
2614 else
2616 /* Write data on DR register */
2617 uint32_t temp;
2618 temp = (uint32_t)(*hsai->pBuffPtr);
2619 hsai->pBuffPtr++;
2620 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2621 hsai->pBuffPtr++;
2622 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2623 hsai->pBuffPtr++;
2624 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2625 hsai->pBuffPtr++;
2626 hsai->Instance->DR = temp;
2627 hsai->XferCount--;
2632 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2633 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2634 * the configuration information for SAI module.
2635 * @retval None
2637 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2639 /* Receive data */
2640 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
2641 hsai->pBuffPtr++;
2642 hsai->XferCount--;
2644 /* Check end of the transfer */
2645 if (hsai->XferCount == 0U)
2647 /* Disable TXE and OVRUDR interrupts */
2648 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2650 /* Clear the SAI Overrun flag */
2651 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2653 hsai->State = HAL_SAI_STATE_READY;
2654 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2655 hsai->RxCpltCallback(hsai);
2656 #else
2657 HAL_SAI_RxCpltCallback(hsai);
2658 #endif
2663 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2664 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2665 * the configuration information for SAI module.
2666 * @retval None
2668 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2670 uint32_t temp;
2672 /* Receive data */
2673 temp = hsai->Instance->DR;
2674 *hsai->pBuffPtr = (uint8_t)temp;
2675 hsai->pBuffPtr++;
2676 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2677 hsai->pBuffPtr++;
2678 hsai->XferCount--;
2680 /* Check end of the transfer */
2681 if (hsai->XferCount == 0U)
2683 /* Disable TXE and OVRUDR interrupts */
2684 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2686 /* Clear the SAI Overrun flag */
2687 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2689 hsai->State = HAL_SAI_STATE_READY;
2690 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2691 hsai->RxCpltCallback(hsai);
2692 #else
2693 HAL_SAI_RxCpltCallback(hsai);
2694 #endif
2699 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2700 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2701 * the configuration information for SAI module.
2702 * @retval None
2704 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2706 uint32_t temp;
2708 /* Receive data */
2709 temp = hsai->Instance->DR;
2710 *hsai->pBuffPtr = (uint8_t)temp;
2711 hsai->pBuffPtr++;
2712 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2713 hsai->pBuffPtr++;
2714 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
2715 hsai->pBuffPtr++;
2716 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
2717 hsai->pBuffPtr++;
2718 hsai->XferCount--;
2720 /* Check end of the transfer */
2721 if (hsai->XferCount == 0U)
2723 /* Disable TXE and OVRUDR interrupts */
2724 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2726 /* Clear the SAI Overrun flag */
2727 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2729 hsai->State = HAL_SAI_STATE_READY;
2730 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2731 hsai->RxCpltCallback(hsai);
2732 #else
2733 HAL_SAI_RxCpltCallback(hsai);
2734 #endif
2739 * @brief DMA SAI transmit process complete callback.
2740 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2741 * the configuration information for the specified DMA module.
2742 * @retval None
2744 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2746 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2748 if (hdma->Init.Mode != DMA_CIRCULAR)
2750 hsai->XferCount = 0;
2752 /* Disable SAI Tx DMA Request */
2753 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2755 /* Stop the interrupts error handling */
2756 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2758 hsai->State = HAL_SAI_STATE_READY;
2760 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2761 hsai->TxCpltCallback(hsai);
2762 #else
2763 HAL_SAI_TxCpltCallback(hsai);
2764 #endif
2768 * @brief DMA SAI transmit process half complete callback.
2769 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2770 * the configuration information for the specified DMA module.
2771 * @retval None
2773 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2775 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2777 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2778 hsai->TxHalfCpltCallback(hsai);
2779 #else
2780 HAL_SAI_TxHalfCpltCallback(hsai);
2781 #endif
2785 * @brief DMA SAI receive process complete callback.
2786 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2787 * the configuration information for the specified DMA module.
2788 * @retval None
2790 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2792 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2794 if (hdma->Init.Mode != DMA_CIRCULAR)
2796 /* Disable Rx DMA Request */
2797 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2798 hsai->XferCount = 0;
2800 /* Stop the interrupts error handling */
2801 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2803 hsai->State = HAL_SAI_STATE_READY;
2805 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2806 hsai->RxCpltCallback(hsai);
2807 #else
2808 HAL_SAI_RxCpltCallback(hsai);
2809 #endif
2813 * @brief DMA SAI receive process half complete callback
2814 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2815 * the configuration information for the specified DMA module.
2816 * @retval None
2818 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2820 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2822 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2823 hsai->RxHalfCpltCallback(hsai);
2824 #else
2825 HAL_SAI_RxHalfCpltCallback(hsai);
2826 #endif
2830 * @brief DMA SAI communication error callback.
2831 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2832 * the configuration information for the specified DMA module.
2833 * @retval None
2835 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2837 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2839 /* Ignore DMA FIFO error */
2840 if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2842 /* Set SAI error code */
2843 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2845 /* Disable the SAI DMA request */
2846 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2848 /* Disable SAI peripheral */
2849 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2850 (void) SAI_Disable(hsai);
2852 /* Set the SAI state ready to be able to start again the process */
2853 hsai->State = HAL_SAI_STATE_READY;
2855 /* Initialize XferCount */
2856 hsai->XferCount = 0U;
2858 /* SAI error Callback */
2859 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2860 hsai->ErrorCallback(hsai);
2861 #else
2862 HAL_SAI_ErrorCallback(hsai);
2863 #endif
2868 * @brief DMA SAI Abort callback.
2869 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2870 * the configuration information for the specified DMA module.
2871 * @retval None
2873 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2875 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2877 /* Disable DMA request */
2878 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2880 /* Disable all interrupts and clear all flags */
2881 hsai->Instance->IMR = 0U;
2882 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2884 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2886 /* Disable SAI peripheral */
2887 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2888 (void) SAI_Disable(hsai);
2890 /* Flush the fifo */
2891 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2893 /* Set the SAI state to ready to be able to start again the process */
2894 hsai->State = HAL_SAI_STATE_READY;
2896 /* Initialize XferCount */
2897 hsai->XferCount = 0U;
2899 /* SAI error Callback */
2900 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2901 hsai->ErrorCallback(hsai);
2902 #else
2903 HAL_SAI_ErrorCallback(hsai);
2904 #endif
2908 * @}
2911 #endif /* HAL_SAI_MODULE_ENABLED */
2913 * @}
2917 * @}
2920 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/