Merge pull request #11494 from haslinghuis/dshot_gpio
[betaflight.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_sai.c
blobbdbdb62b3939699329d15f6bf282c5598890bca7
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_DEFAULT_TIMEOUT 4U
248 #define SAI_LONG_TIMEOUT 1000U
250 * @}
253 /* Private macro -------------------------------------------------------------*/
254 /* Private variables ---------------------------------------------------------*/
255 /* Private function prototypes -----------------------------------------------*/
256 /** @defgroup SAI_Private_Functions SAI Private Functions
257 * @{
259 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
260 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
261 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
262 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
264 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
265 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
266 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
267 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
268 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
269 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
270 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
272 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
273 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
274 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
275 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
276 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
277 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
279 * @}
282 /* Exported functions ---------------------------------------------------------*/
283 /** @defgroup SAI_Exported_Functions SAI Exported Functions
284 * @{
287 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
288 * @brief Initialization and Configuration functions
290 @verbatim
291 ===============================================================================
292 ##### Initialization and de-initialization functions #####
293 ===============================================================================
294 [..] This subsection provides a set of functions allowing to initialize and
295 de-initialize the SAIx peripheral:
297 (+) User must implement HAL_SAI_MspInit() function in which he configures
298 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
300 (+) Call the function HAL_SAI_Init() to configure the selected device with
301 the selected configuration:
302 (++) Mode (Master/slave TX/RX)
303 (++) Protocol
304 (++) Data Size
305 (++) MCLK Output
306 (++) Audio frequency
307 (++) FIFO Threshold
308 (++) Frame Config
309 (++) Slot Config
310 (++) PDM Config
312 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
313 of the selected SAI peripheral.
315 @endverbatim
316 * @{
320 * @brief Initialize the structure FrameInit, SlotInit and the low part of
321 * Init according to the specified parameters and call the function
322 * HAL_SAI_Init to initialize the SAI block.
323 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
324 * the configuration information for SAI module.
325 * @param protocol one of the supported protocol @ref SAI_Protocol
326 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
327 * the configuration information for SAI module.
328 * @param nbslot Number of slot.
329 * @retval HAL status
331 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
333 HAL_StatusTypeDef status;
335 /* Check the parameters */
336 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
337 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
339 switch (protocol)
341 case SAI_I2S_STANDARD :
342 case SAI_I2S_MSBJUSTIFIED :
343 case SAI_I2S_LSBJUSTIFIED :
344 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
345 break;
346 case SAI_PCM_LONG :
347 case SAI_PCM_SHORT :
348 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
349 break;
350 default :
351 status = HAL_ERROR;
352 break;
355 if (status == HAL_OK)
357 status = HAL_SAI_Init(hsai);
360 return status;
364 * @brief Initialize the SAI according to the specified parameters.
365 * in the SAI_InitTypeDef structure and initialize the associated handle.
366 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
367 * the configuration information for SAI module.
368 * @retval HAL status
370 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
372 uint32_t tmpregisterGCR;
373 uint32_t ckstr_bits;
374 uint32_t syncen_bits;
375 SAI_TypeDef *SaiBaseAddress;
377 /* Check the SAI handle allocation */
378 if (hsai == NULL)
380 return HAL_ERROR;
383 /* check the instance */
384 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
386 /* Check the SAI Block parameters */
387 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
388 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
389 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
390 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
391 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
392 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
393 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
394 #if defined(SAI_VER_V2_X)
395 /* SAI Peripheral version depends on STM32H7 device revision ID */
396 if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
398 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
400 #else /* SAI_VER_V2_1 */
401 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
402 #endif /* SAI_VER_V2_X */
403 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
404 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
405 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
406 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
407 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
408 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
409 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
410 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
412 /* Check the SAI Block Frame parameters */
413 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
414 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
415 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
416 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
417 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
419 /* Check the SAI Block Slot parameters */
420 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
421 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
422 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
423 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
425 /* Check the SAI PDM parameters */
426 assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
427 if (hsai->Init.PdmInit.Activation == ENABLE)
429 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
430 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
431 /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
432 #if defined(SAI4)
433 if (((hsai->Instance != SAI1_Block_A) && (hsai->Instance != SAI4_Block_A)) ||
434 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
435 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
437 return HAL_ERROR;
439 #else
440 if ((hsai->Instance != SAI1_Block_A) ||
441 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
442 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
444 return HAL_ERROR;
446 #endif /* SAI4 */
449 /* Get the SAI base address according to the SAI handle */
450 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
452 SaiBaseAddress = SAI1;
454 #if defined(SAI2)
455 else if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
457 SaiBaseAddress = SAI2;
459 #endif /* SAI2 */
460 #if defined(SAI3)
461 else if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
463 SaiBaseAddress = SAI3;
465 #endif /* SAI3 */
466 #if defined(SAI4)
467 else if ((hsai->Instance == SAI4_Block_A) || (hsai->Instance == SAI4_Block_B))
469 SaiBaseAddress = SAI4;
471 #endif /* SAI4 */
472 else
474 return HAL_ERROR;
477 if (hsai->State == HAL_SAI_STATE_RESET)
479 /* Allocate lock resource and initialize it */
480 hsai->Lock = HAL_UNLOCKED;
482 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
483 /* Reset callback pointers to the weak predefined callbacks */
484 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
485 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
486 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
487 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
488 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
490 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
491 if (hsai->MspInitCallback == NULL)
493 hsai->MspInitCallback = HAL_SAI_MspInit;
495 hsai->MspInitCallback(hsai);
496 #else
497 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
498 HAL_SAI_MspInit(hsai);
499 #endif
502 /* Disable the selected SAI peripheral */
503 if(SAI_Disable(hsai) != HAL_OK)
505 return HAL_ERROR;
508 hsai->State = HAL_SAI_STATE_BUSY;
510 /* SAI Block Synchro Configuration -----------------------------------------*/
511 /* This setting must be done with both audio block (A & B) disabled */
512 switch (hsai->Init.SynchroExt)
514 case SAI_SYNCEXT_DISABLE :
515 tmpregisterGCR = 0;
516 break;
517 case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
518 tmpregisterGCR = SAI_GCR_SYNCOUT_0;
519 break;
520 case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
521 tmpregisterGCR = SAI_GCR_SYNCOUT_1;
522 break;
523 default:
524 tmpregisterGCR = 0;
525 break;
528 switch (hsai->Init.Synchro)
530 case SAI_ASYNCHRONOUS :
531 syncen_bits = 0;
532 break;
533 case SAI_SYNCHRONOUS :
534 syncen_bits = SAI_xCR1_SYNCEN_0;
535 break;
536 case SAI_SYNCHRONOUS_EXT_SAI1 :
537 syncen_bits = SAI_xCR1_SYNCEN_1;
538 break;
539 #if defined(SAI2)
540 case SAI_SYNCHRONOUS_EXT_SAI2 :
541 syncen_bits = SAI_xCR1_SYNCEN_1;
542 tmpregisterGCR |= SAI_GCR_SYNCIN_0;
543 break;
544 #endif /* SAI2 */
545 #if defined(SAI3)
546 case SAI_SYNCHRONOUS_EXT_SAI3 :
547 syncen_bits = SAI_xCR1_SYNCEN_1;
548 tmpregisterGCR |= SAI_GCR_SYNCIN_1;
549 break;
550 #endif /* SAI3 */
551 #if defined(SAI4)
552 case SAI_SYNCHRONOUS_EXT_SAI4 :
553 syncen_bits = SAI_xCR1_SYNCEN_1;
554 tmpregisterGCR |= (SAI_GCR_SYNCIN_1 | SAI_GCR_SYNCIN_0);
555 break;
556 #endif /* SAI4 */
557 default:
558 syncen_bits = 0;
559 break;
562 /* Set the SAI Block Synchro Configuration */
563 SaiBaseAddress->GCR = tmpregisterGCR;
565 if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
567 uint32_t freq = 0;
568 uint32_t tmpval;
570 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
571 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
573 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
576 #if defined(SAI2)
577 #if defined(RCC_PERIPHCLK_SAI2)
578 if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
580 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
582 #else
583 if (hsai->Instance == SAI2_Block_A)
585 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A);
587 if (hsai->Instance == SAI2_Block_B)
589 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B);
591 #endif /* RCC_PERIPHCLK_SAI2 */
592 #endif /* SAI2 */
594 #if defined(SAI3)
595 if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
597 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3);
599 #endif /* SAI3 */
600 #if defined(SAI4)
601 if (hsai->Instance == SAI4_Block_A)
603 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A);
605 if (hsai->Instance == SAI4_Block_B)
607 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B);
609 #endif /* SAI4 */
611 /* Configure Master Clock Divider using the following formula :
612 - If NODIV = 1 :
613 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
614 - If NODIV = 0 :
615 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
616 if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
618 /* NODIV = 1 */
619 uint32_t tmpframelength;
621 if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
623 /* For SPDIF protocol, frame length is set by hardware to 64 */
624 tmpframelength = 64U;
626 else if (hsai->Init.Protocol == SAI_AC97_PROTOCOL)
628 /* For AC97 protocol, frame length is set by hardware to 256 */
629 tmpframelength = 256U;
631 else
633 /* For free protocol, frame length is set by user */
634 tmpframelength = hsai->FrameInit.FrameLength;
637 /* (freq x 10) to keep Significant digits */
638 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmpframelength);
640 else
642 /* NODIV = 0 */
643 uint32_t tmposr;
644 tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
645 /* (freq x 10) to keep Significant digits */
646 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
648 hsai->Init.Mckdiv = tmpval / 10U;
650 /* Round result to the nearest integer */
651 if ((tmpval % 10U) > 8U)
653 hsai->Init.Mckdiv += 1U;
656 /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
657 if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
659 hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
663 /* Check the SAI Block master clock divider parameter */
664 assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
666 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
667 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
669 /* Transmit */
670 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
672 else
674 /* Receive */
675 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
678 /* SAI Block Configuration -------------------------------------------------*/
679 /* SAI CR1 Configuration */
680 #if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
682 if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
684 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
685 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
686 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
687 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
688 SAI_xCR1_MCKEN);
690 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
691 hsai->Init.DataSize | hsai->Init.FirstBit | \
692 ckstr_bits | syncen_bits | \
693 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
694 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
695 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
697 else /* STM32H7xx Rev.Y */
699 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
700 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
701 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
702 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR);
704 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
705 hsai->Init.DataSize | hsai->Init.FirstBit | \
706 ckstr_bits | syncen_bits | \
707 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
708 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
709 hsai->Init.MckOverSampling);
711 #else /* SAI_VER_V2_1*/
712 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
713 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
714 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
715 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
716 SAI_xCR1_MCKEN);
718 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
719 hsai->Init.DataSize | hsai->Init.FirstBit | \
720 ckstr_bits | syncen_bits | \
721 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
722 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
723 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
724 #endif /* SAI_VER_V2_X */
726 /* SAI CR2 Configuration */
727 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
728 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
730 /* SAI Frame Configuration -----------------------------------------*/
731 hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
732 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
733 hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
734 hsai->FrameInit.FSOffset |
735 hsai->FrameInit.FSDefinition |
736 hsai->FrameInit.FSPolarity |
737 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
739 /* SAI Block_x SLOT Configuration ------------------------------------------*/
740 /* This register has no meaning in AC 97 and SPDIF audio protocol */
741 hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
742 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
744 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
745 (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8);
747 /* SAI PDM Configuration ---------------------------------------------------*/
748 #if defined(SAI4)
749 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
750 #else
751 if (hsai->Instance == SAI1_Block_A)
752 #endif /* SAI4 */
754 /* Disable PDM interface */
755 SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
756 if (hsai->Init.PdmInit.Activation == ENABLE)
758 /* Configure and enable PDM interface */
759 SaiBaseAddress->PDMCR = (hsai->Init.PdmInit.ClockEnable |
760 ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
761 SaiBaseAddress->PDMCR |= SAI_PDMCR_PDMEN;
765 /* Initialize the error code */
766 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
768 /* Initialize the SAI state */
769 hsai->State = HAL_SAI_STATE_READY;
771 /* Release Lock */
772 __HAL_UNLOCK(hsai);
774 return HAL_OK;
778 * @brief DeInitialize the SAI peripheral.
779 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
780 * the configuration information for SAI module.
781 * @retval HAL status
783 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
785 SAI_TypeDef *SaiBaseAddress;
787 /* Check the SAI handle allocation */
788 if (hsai == NULL)
790 return HAL_ERROR;
793 hsai->State = HAL_SAI_STATE_BUSY;
795 /* Disabled All interrupt and clear all the flag */
796 hsai->Instance->IMR = 0;
797 hsai->Instance->CLRFR = 0xFFFFFFFFU;
799 /* Disable the SAI */
800 if (SAI_Disable(hsai) != HAL_OK)
802 /* Reset SAI state to ready */
803 hsai->State = HAL_SAI_STATE_READY;
805 /* Release Lock */
806 __HAL_UNLOCK(hsai);
808 return HAL_ERROR;
811 /* Flush the fifo */
812 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
814 /* Disable SAI PDM interface */
815 #if defined(SAI4)
816 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
817 #else
818 if (hsai->Instance == SAI1_Block_A)
819 #endif /* SAI4 */
821 /* Get the SAI base address according to the SAI handle */
822 #if defined(SAI4)
823 SaiBaseAddress = (hsai->Instance == SAI1_Block_A) ? SAI1 : SAI4;
824 #else
825 SaiBaseAddress = SAI1;
826 #endif /* SAI4 */
828 /* Reset PDM delays */
829 SaiBaseAddress->PDMDLY = 0U;
831 /* Disable PDM interface */
832 SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
835 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
836 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
837 if (hsai->MspDeInitCallback == NULL)
839 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
841 hsai->MspDeInitCallback(hsai);
842 #else
843 HAL_SAI_MspDeInit(hsai);
844 #endif
846 /* Initialize the error code */
847 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
849 /* Initialize the SAI state */
850 hsai->State = HAL_SAI_STATE_RESET;
852 /* Release Lock */
853 __HAL_UNLOCK(hsai);
855 return HAL_OK;
859 * @brief Initialize the SAI MSP.
860 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
861 * the configuration information for SAI module.
862 * @retval None
864 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
866 /* Prevent unused argument(s) compilation warning */
867 UNUSED(hsai);
869 /* NOTE : This function should not be modified, when the callback is needed,
870 the HAL_SAI_MspInit could be implemented in the user file
875 * @brief DeInitialize the SAI MSP.
876 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
877 * the configuration information for SAI module.
878 * @retval None
880 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
882 /* Prevent unused argument(s) compilation warning */
883 UNUSED(hsai);
885 /* NOTE : This function should not be modified, when the callback is needed,
886 the HAL_SAI_MspDeInit could be implemented in the user file
890 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
892 * @brief Register a user SAI callback
893 * to be used instead of the weak predefined callback.
894 * @param hsai SAI handle.
895 * @param CallbackID ID of the callback to be registered.
896 * This parameter can be one of the following values:
897 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
898 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
899 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
900 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
901 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
902 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
903 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
904 * @param pCallback pointer to the callback function.
905 * @retval HAL status.
907 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
908 HAL_SAI_CallbackIDTypeDef CallbackID,
909 pSAI_CallbackTypeDef pCallback)
911 HAL_StatusTypeDef status = HAL_OK;
913 if (pCallback == NULL)
915 /* update the error code */
916 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
917 /* update return status */
918 status = HAL_ERROR;
920 else
922 if (HAL_SAI_STATE_READY == hsai->State)
924 switch (CallbackID)
926 case HAL_SAI_RX_COMPLETE_CB_ID :
927 hsai->RxCpltCallback = pCallback;
928 break;
929 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
930 hsai->RxHalfCpltCallback = pCallback;
931 break;
932 case HAL_SAI_TX_COMPLETE_CB_ID :
933 hsai->TxCpltCallback = pCallback;
934 break;
935 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
936 hsai->TxHalfCpltCallback = pCallback;
937 break;
938 case HAL_SAI_ERROR_CB_ID :
939 hsai->ErrorCallback = pCallback;
940 break;
941 case HAL_SAI_MSPINIT_CB_ID :
942 hsai->MspInitCallback = pCallback;
943 break;
944 case HAL_SAI_MSPDEINIT_CB_ID :
945 hsai->MspDeInitCallback = pCallback;
946 break;
947 default :
948 /* update the error code */
949 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
950 /* update return status */
951 status = HAL_ERROR;
952 break;
955 else if (HAL_SAI_STATE_RESET == hsai->State)
957 switch (CallbackID)
959 case HAL_SAI_MSPINIT_CB_ID :
960 hsai->MspInitCallback = pCallback;
961 break;
962 case HAL_SAI_MSPDEINIT_CB_ID :
963 hsai->MspDeInitCallback = pCallback;
964 break;
965 default :
966 /* update the error code */
967 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
968 /* update return status */
969 status = HAL_ERROR;
970 break;
973 else
975 /* update the error code */
976 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
977 /* update return status */
978 status = HAL_ERROR;
981 return status;
985 * @brief Unregister a user SAI callback.
986 * SAI callback is redirected to the weak predefined callback.
987 * @param hsai SAI handle.
988 * @param CallbackID ID of the callback to be unregistered.
989 * This parameter can be one of the following values:
990 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
991 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
992 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
993 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
994 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
995 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
996 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
997 * @retval HAL status.
999 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
1000 HAL_SAI_CallbackIDTypeDef CallbackID)
1002 HAL_StatusTypeDef status = HAL_OK;
1004 if (HAL_SAI_STATE_READY == hsai->State)
1006 switch (CallbackID)
1008 case HAL_SAI_RX_COMPLETE_CB_ID :
1009 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
1010 break;
1011 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
1012 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
1013 break;
1014 case HAL_SAI_TX_COMPLETE_CB_ID :
1015 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
1016 break;
1017 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
1018 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
1019 break;
1020 case HAL_SAI_ERROR_CB_ID :
1021 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
1022 break;
1023 case HAL_SAI_MSPINIT_CB_ID :
1024 hsai->MspInitCallback = HAL_SAI_MspInit;
1025 break;
1026 case HAL_SAI_MSPDEINIT_CB_ID :
1027 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1028 break;
1029 default :
1030 /* update the error code */
1031 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1032 /* update return status */
1033 status = HAL_ERROR;
1034 break;
1037 else if (HAL_SAI_STATE_RESET == hsai->State)
1039 switch (CallbackID)
1041 case HAL_SAI_MSPINIT_CB_ID :
1042 hsai->MspInitCallback = HAL_SAI_MspInit;
1043 break;
1044 case HAL_SAI_MSPDEINIT_CB_ID :
1045 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
1046 break;
1047 default :
1048 /* update the error code */
1049 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1050 /* update return status */
1051 status = HAL_ERROR;
1052 break;
1055 else
1057 /* update the error code */
1058 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
1059 /* update return status */
1060 status = HAL_ERROR;
1062 return status;
1064 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1067 * @}
1070 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
1071 * @brief Data transfers functions
1073 @verbatim
1074 ==============================================================================
1075 ##### IO operation functions #####
1076 ==============================================================================
1077 [..]
1078 This subsection provides a set of functions allowing to manage the SAI data
1079 transfers.
1081 (+) There are two modes of transfer:
1082 (++) Blocking mode : The communication is performed in the polling mode.
1083 The status of all data processing is returned by the same function
1084 after finishing transfer.
1085 (++) No-Blocking mode : The communication is performed using Interrupts
1086 or DMA. These functions return the status of the transfer startup.
1087 The end of the data processing will be indicated through the
1088 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
1089 using DMA mode.
1091 (+) Blocking mode functions are :
1092 (++) HAL_SAI_Transmit()
1093 (++) HAL_SAI_Receive()
1095 (+) Non Blocking mode functions with Interrupt are :
1096 (++) HAL_SAI_Transmit_IT()
1097 (++) HAL_SAI_Receive_IT()
1099 (+) Non Blocking mode functions with DMA are :
1100 (++) HAL_SAI_Transmit_DMA()
1101 (++) HAL_SAI_Receive_DMA()
1103 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1104 (++) HAL_SAI_TxCpltCallback()
1105 (++) HAL_SAI_RxCpltCallback()
1106 (++) HAL_SAI_ErrorCallback()
1108 @endverbatim
1109 * @{
1113 * @brief Transmit an amount of data in blocking mode.
1114 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1115 * the configuration information for SAI module.
1116 * @param pData Pointer to data buffer
1117 * @param Size Amount of data to be sent
1118 * @param Timeout Timeout duration
1119 * @retval HAL status
1121 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1123 uint32_t tickstart = HAL_GetTick();
1124 uint32_t temp;
1126 if ((pData == NULL) || (Size == 0U))
1128 return HAL_ERROR;
1131 if (hsai->State == HAL_SAI_STATE_READY)
1133 /* Process Locked */
1134 __HAL_LOCK(hsai);
1136 hsai->XferSize = Size;
1137 hsai->XferCount = Size;
1138 hsai->pBuffPtr = pData;
1139 hsai->State = HAL_SAI_STATE_BUSY_TX;
1140 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1142 /* Check if the SAI is already enabled */
1143 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1145 /* fill the fifo with data before to enabled the SAI */
1146 SAI_FillFifo(hsai);
1147 /* Enable SAI peripheral */
1148 __HAL_SAI_ENABLE(hsai);
1151 while (hsai->XferCount > 0U)
1153 /* Write data if the FIFO is not full */
1154 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
1156 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1158 hsai->Instance->DR = *hsai->pBuffPtr;
1159 hsai->pBuffPtr++;
1161 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1163 temp = (uint32_t)(*hsai->pBuffPtr);
1164 hsai->pBuffPtr++;
1165 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1166 hsai->pBuffPtr++;
1167 hsai->Instance->DR = temp;
1169 else
1171 temp = (uint32_t)(*hsai->pBuffPtr);
1172 hsai->pBuffPtr++;
1173 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1174 hsai->pBuffPtr++;
1175 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
1176 hsai->pBuffPtr++;
1177 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
1178 hsai->pBuffPtr++;
1179 hsai->Instance->DR = temp;
1181 hsai->XferCount--;
1183 else
1185 /* Check for the Timeout */
1186 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1188 /* Update error code */
1189 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1191 /* Clear all the flags */
1192 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1194 /* Disable SAI peripheral */
1195 /* No need to check return value because state update, unlock and error return will be performed later */
1196 (void) SAI_Disable(hsai);
1198 /* Flush the fifo */
1199 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1201 /* Change the SAI state */
1202 hsai->State = HAL_SAI_STATE_READY;
1204 /* Process Unlocked */
1205 __HAL_UNLOCK(hsai);
1207 return HAL_ERROR;
1212 hsai->State = HAL_SAI_STATE_READY;
1214 /* Process Unlocked */
1215 __HAL_UNLOCK(hsai);
1217 return HAL_OK;
1219 else
1221 return HAL_BUSY;
1226 * @brief Receive an amount of data in blocking mode.
1227 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1228 * the configuration information for SAI module.
1229 * @param pData Pointer to data buffer
1230 * @param Size Amount of data to be received
1231 * @param Timeout Timeout duration
1232 * @retval HAL status
1234 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1236 uint32_t tickstart = HAL_GetTick();
1237 uint32_t temp;
1239 if ((pData == NULL) || (Size == 0U))
1241 return HAL_ERROR;
1244 if (hsai->State == HAL_SAI_STATE_READY)
1246 /* Process Locked */
1247 __HAL_LOCK(hsai);
1249 hsai->pBuffPtr = pData;
1250 hsai->XferSize = Size;
1251 hsai->XferCount = Size;
1252 hsai->State = HAL_SAI_STATE_BUSY_RX;
1253 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1255 /* Check if the SAI is already enabled */
1256 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1258 /* Enable SAI peripheral */
1259 __HAL_SAI_ENABLE(hsai);
1262 /* Receive data */
1263 while (hsai->XferCount > 0U)
1265 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1267 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1269 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
1270 hsai->pBuffPtr++;
1272 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1274 temp = hsai->Instance->DR;
1275 *hsai->pBuffPtr = (uint8_t)temp;
1276 hsai->pBuffPtr++;
1277 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1278 hsai->pBuffPtr++;
1280 else
1282 temp = hsai->Instance->DR;
1283 *hsai->pBuffPtr = (uint8_t)temp;
1284 hsai->pBuffPtr++;
1285 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1286 hsai->pBuffPtr++;
1287 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
1288 hsai->pBuffPtr++;
1289 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
1290 hsai->pBuffPtr++;
1292 hsai->XferCount--;
1294 else
1296 /* Check for the Timeout */
1297 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1299 /* Update error code */
1300 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1302 /* Clear all the flags */
1303 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1305 /* Disable SAI peripheral */
1306 /* No need to check return value because state update, unlock and error return will be performed later */
1307 (void) SAI_Disable(hsai);
1309 /* Flush the fifo */
1310 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1312 /* Change the SAI state */
1313 hsai->State = HAL_SAI_STATE_READY;
1315 /* Process Unlocked */
1316 __HAL_UNLOCK(hsai);
1318 return HAL_ERROR;
1323 hsai->State = HAL_SAI_STATE_READY;
1325 /* Process Unlocked */
1326 __HAL_UNLOCK(hsai);
1328 return HAL_OK;
1330 else
1332 return HAL_BUSY;
1337 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1338 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1339 * the configuration information for SAI module.
1340 * @param pData Pointer to data buffer
1341 * @param Size Amount of data to be sent
1342 * @retval HAL status
1344 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1346 if ((pData == NULL) || (Size == 0U))
1348 return HAL_ERROR;
1351 if (hsai->State == HAL_SAI_STATE_READY)
1353 /* Process Locked */
1354 __HAL_LOCK(hsai);
1356 hsai->pBuffPtr = pData;
1357 hsai->XferSize = Size;
1358 hsai->XferCount = Size;
1359 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1360 hsai->State = HAL_SAI_STATE_BUSY_TX;
1362 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1364 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1366 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1368 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1370 else
1372 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1375 /* Fill the fifo before starting the communication */
1376 SAI_FillFifo(hsai);
1378 /* Enable FRQ and OVRUDR interrupts */
1379 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1381 /* Check if the SAI is already enabled */
1382 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1384 /* Enable SAI peripheral */
1385 __HAL_SAI_ENABLE(hsai);
1387 /* Process Unlocked */
1388 __HAL_UNLOCK(hsai);
1390 return HAL_OK;
1392 else
1394 return HAL_BUSY;
1399 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1400 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1401 * the configuration information for SAI module.
1402 * @param pData Pointer to data buffer
1403 * @param Size Amount of data to be received
1404 * @retval HAL status
1406 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1408 if ((pData == NULL) || (Size == 0U))
1410 return HAL_ERROR;
1413 if (hsai->State == HAL_SAI_STATE_READY)
1415 /* Process Locked */
1416 __HAL_LOCK(hsai);
1418 hsai->pBuffPtr = pData;
1419 hsai->XferSize = Size;
1420 hsai->XferCount = Size;
1421 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1422 hsai->State = HAL_SAI_STATE_BUSY_RX;
1424 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1426 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1428 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1430 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1432 else
1434 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1437 /* Enable TXE and OVRUDR interrupts */
1438 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1440 /* Check if the SAI is already enabled */
1441 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1443 /* Enable SAI peripheral */
1444 __HAL_SAI_ENABLE(hsai);
1447 /* Process Unlocked */
1448 __HAL_UNLOCK(hsai);
1450 return HAL_OK;
1452 else
1454 return HAL_BUSY;
1459 * @brief Pause the audio stream playing from the Media.
1460 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1461 * the configuration information for SAI module.
1462 * @retval HAL status
1464 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1466 /* Process Locked */
1467 __HAL_LOCK(hsai);
1469 /* Pause the audio file playing by disabling the SAI DMA requests */
1470 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1472 /* Process Unlocked */
1473 __HAL_UNLOCK(hsai);
1475 return HAL_OK;
1479 * @brief Resume the audio stream playing from the Media.
1480 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1481 * the configuration information for SAI module.
1482 * @retval HAL status
1484 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1486 /* Process Locked */
1487 __HAL_LOCK(hsai);
1489 /* Enable the SAI DMA requests */
1490 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1492 /* If the SAI peripheral is still not enabled, enable it */
1493 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1495 /* Enable SAI peripheral */
1496 __HAL_SAI_ENABLE(hsai);
1499 /* Process Unlocked */
1500 __HAL_UNLOCK(hsai);
1502 return HAL_OK;
1506 * @brief Stop the audio stream playing from the Media.
1507 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1508 * the configuration information for SAI module.
1509 * @retval HAL status
1511 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1513 HAL_StatusTypeDef status = HAL_OK;
1515 /* Process Locked */
1516 __HAL_LOCK(hsai);
1518 /* Disable the SAI DMA request */
1519 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1521 /* Abort the SAI Tx DMA Stream */
1522 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1524 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1526 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1527 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1529 status = HAL_ERROR;
1530 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1535 /* Abort the SAI Rx DMA Stream */
1536 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1538 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1540 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1541 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1543 status = HAL_ERROR;
1544 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1549 /* Disable SAI peripheral */
1550 if (SAI_Disable(hsai) != HAL_OK)
1552 status = HAL_ERROR;
1555 /* Flush the fifo */
1556 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1558 /* Set hsai state to ready */
1559 hsai->State = HAL_SAI_STATE_READY;
1561 /* Process Unlocked */
1562 __HAL_UNLOCK(hsai);
1564 return status;
1568 * @brief Abort the current transfer and disable the SAI.
1569 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1570 * the configuration information for SAI module.
1571 * @retval HAL status
1573 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1575 HAL_StatusTypeDef status = HAL_OK;
1577 /* Process Locked */
1578 __HAL_LOCK(hsai);
1580 /* Check SAI DMA is enabled or not */
1581 if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1583 /* Disable the SAI DMA request */
1584 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1586 /* Abort the SAI Tx DMA Stream */
1587 if ((hsai->State == HAL_SAI_STATE_BUSY_TX)&& (hsai->hdmatx != NULL))
1589 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1591 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1592 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1594 status = HAL_ERROR;
1595 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1600 /* Abort the SAI Rx DMA Stream */
1601 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1603 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1605 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1606 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1608 status = HAL_ERROR;
1609 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1615 /* Disabled All interrupt and clear all the flag */
1616 hsai->Instance->IMR = 0;
1617 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1619 /* Disable SAI peripheral */
1620 if (SAI_Disable(hsai) != HAL_OK)
1622 status = HAL_ERROR;
1625 /* Flush the fifo */
1626 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1628 /* Set hsai state to ready */
1629 hsai->State = HAL_SAI_STATE_READY;
1631 /* Process Unlocked */
1632 __HAL_UNLOCK(hsai);
1634 return status;
1638 * @brief Transmit an amount of data in non-blocking mode with DMA.
1639 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1640 * the configuration information for SAI module.
1641 * @param pData Pointer to data buffer
1642 * @param Size Amount of data to be sent
1643 * @retval HAL status
1645 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1647 uint32_t tickstart = HAL_GetTick();
1649 if ((pData == NULL) || (Size == 0U))
1651 return HAL_ERROR;
1654 if (hsai->State == HAL_SAI_STATE_READY)
1656 /* Process Locked */
1657 __HAL_LOCK(hsai);
1659 hsai->pBuffPtr = pData;
1660 hsai->XferSize = Size;
1661 hsai->XferCount = Size;
1662 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1663 hsai->State = HAL_SAI_STATE_BUSY_TX;
1665 /* Set the SAI Tx DMA Half transfer complete callback */
1666 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1668 /* Set the SAI TxDMA transfer complete callback */
1669 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1671 /* Set the DMA error callback */
1672 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1674 /* Set the DMA Tx abort callback */
1675 hsai->hdmatx->XferAbortCallback = NULL;
1677 /* Enable the Tx DMA Stream */
1678 if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1680 __HAL_UNLOCK(hsai);
1681 return HAL_ERROR;
1684 /* Enable the interrupts for error handling */
1685 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1687 /* Enable SAI Tx DMA Request */
1688 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1690 /* Wait untill FIFO is not empty */
1691 while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1693 /* Check for the Timeout */
1694 if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1696 /* Update error code */
1697 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1699 /* Process Unlocked */
1700 __HAL_UNLOCK(hsai);
1702 return HAL_TIMEOUT;
1706 /* Check if the SAI is already enabled */
1707 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1709 /* Enable SAI peripheral */
1710 __HAL_SAI_ENABLE(hsai);
1713 /* Process Unlocked */
1714 __HAL_UNLOCK(hsai);
1716 return HAL_OK;
1718 else
1720 return HAL_BUSY;
1725 * @brief Receive an amount of data in non-blocking mode with DMA.
1726 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1727 * the configuration information for SAI module.
1728 * @param pData Pointer to data buffer
1729 * @param Size Amount of data to be received
1730 * @retval HAL status
1732 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1735 if ((pData == NULL) || (Size == 0U))
1737 return HAL_ERROR;
1740 if (hsai->State == HAL_SAI_STATE_READY)
1742 /* Process Locked */
1743 __HAL_LOCK(hsai);
1745 hsai->pBuffPtr = pData;
1746 hsai->XferSize = Size;
1747 hsai->XferCount = Size;
1748 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1749 hsai->State = HAL_SAI_STATE_BUSY_RX;
1751 /* Set the SAI Rx DMA Half transfer complete callback */
1752 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1754 /* Set the SAI Rx DMA transfer complete callback */
1755 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1757 /* Set the DMA error callback */
1758 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1760 /* Set the DMA Rx abort callback */
1761 hsai->hdmarx->XferAbortCallback = NULL;
1763 /* Enable the Rx DMA Stream */
1764 if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1766 __HAL_UNLOCK(hsai);
1767 return HAL_ERROR;
1770 /* Enable the interrupts for error handling */
1771 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1773 /* Enable SAI Rx DMA Request */
1774 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1776 /* Check if the SAI is already enabled */
1777 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1779 /* Enable SAI peripheral */
1780 __HAL_SAI_ENABLE(hsai);
1783 /* Process Unlocked */
1784 __HAL_UNLOCK(hsai);
1786 return HAL_OK;
1788 else
1790 return HAL_BUSY;
1795 * @brief Enable the Tx mute mode.
1796 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1797 * the configuration information for SAI module.
1798 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1799 * @retval HAL status
1801 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1803 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1805 if (hsai->State != HAL_SAI_STATE_RESET)
1807 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1808 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
1809 return HAL_OK;
1811 return HAL_ERROR;
1815 * @brief Disable the Tx mute mode.
1816 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1817 * the configuration information for SAI module.
1818 * @retval HAL status
1820 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1822 if (hsai->State != HAL_SAI_STATE_RESET)
1824 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1825 return HAL_OK;
1827 return HAL_ERROR;
1831 * @brief Enable the Rx mute detection.
1832 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1833 * the configuration information for SAI module.
1834 * @param callback function called when the mute is detected.
1835 * @param counter number a data before mute detection max 63.
1836 * @retval HAL status
1838 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1840 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1842 if (hsai->State != HAL_SAI_STATE_RESET)
1844 /* set the mute counter */
1845 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1846 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1847 hsai->mutecallback = callback;
1848 /* enable the IT interrupt */
1849 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1850 return HAL_OK;
1852 return HAL_ERROR;
1856 * @brief Disable the Rx mute detection.
1857 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1858 * the configuration information for SAI module.
1859 * @retval HAL status
1861 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1863 if (hsai->State != HAL_SAI_STATE_RESET)
1865 /* set the mutecallback to NULL */
1866 hsai->mutecallback = NULL;
1867 /* enable the IT interrupt */
1868 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1869 return HAL_OK;
1871 return HAL_ERROR;
1875 * @brief Handle SAI interrupt request.
1876 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1877 * the configuration information for SAI module.
1878 * @retval None
1880 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1882 if (hsai->State != HAL_SAI_STATE_RESET)
1884 uint32_t itflags = hsai->Instance->SR;
1885 uint32_t itsources = hsai->Instance->IMR;
1886 uint32_t cr1config = hsai->Instance->CR1;
1887 uint32_t tmperror;
1889 /* SAI Fifo request interrupt occured ------------------------------------*/
1890 if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1892 hsai->InterruptServiceRoutine(hsai);
1894 /* SAI Overrun error interrupt occurred ----------------------------------*/
1895 else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1897 /* Clear the SAI Overrun flag */
1898 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1899 /* Get the SAI error code */
1900 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1901 /* Change the SAI error code */
1902 hsai->ErrorCode |= tmperror;
1903 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1904 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1905 hsai->ErrorCallback(hsai);
1906 #else
1907 HAL_SAI_ErrorCallback(hsai);
1908 #endif
1910 /* SAI mutedet interrupt occurred ----------------------------------*/
1911 else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1913 /* Clear the SAI mutedet flag */
1914 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1915 /* call the call back function */
1916 if (hsai->mutecallback != NULL)
1918 /* inform the user that an RX mute event has been detected */
1919 hsai->mutecallback();
1922 /* SAI AFSDET interrupt occurred ----------------------------------*/
1923 else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1925 /* Clear the SAI AFSDET flag */
1926 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1928 /* Change the SAI error code */
1929 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1931 /* Check SAI DMA is enabled or not */
1932 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1934 /* Abort the SAI DMA Streams */
1935 if (hsai->hdmatx != NULL)
1937 /* Set the DMA Tx abort callback */
1938 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1940 /* Abort DMA in IT mode */
1941 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1943 /* Update SAI error code */
1944 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1946 /* Call SAI error callback */
1947 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1948 hsai->ErrorCallback(hsai);
1949 #else
1950 HAL_SAI_ErrorCallback(hsai);
1951 #endif
1954 if (hsai->hdmarx != NULL)
1956 /* Set the DMA Rx abort callback */
1957 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1959 /* Abort DMA in IT mode */
1960 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1962 /* Update SAI error code */
1963 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1965 /* Call SAI error callback */
1966 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1967 hsai->ErrorCallback(hsai);
1968 #else
1969 HAL_SAI_ErrorCallback(hsai);
1970 #endif
1974 else
1976 /* Abort SAI */
1977 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1978 (void) HAL_SAI_Abort(hsai);
1980 /* Set error callback */
1981 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1982 hsai->ErrorCallback(hsai);
1983 #else
1984 HAL_SAI_ErrorCallback(hsai);
1985 #endif
1988 /* SAI LFSDET interrupt occurred ----------------------------------*/
1989 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1991 /* Clear the SAI LFSDET flag */
1992 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1994 /* Change the SAI error code */
1995 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1997 /* Check SAI DMA is enabled or not */
1998 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
2000 /* Abort the SAI DMA Streams */
2001 if (hsai->hdmatx != NULL)
2003 /* Set the DMA Tx abort callback */
2004 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
2006 /* Abort DMA in IT mode */
2007 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
2009 /* Update SAI error code */
2010 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2012 /* Call SAI error callback */
2013 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2014 hsai->ErrorCallback(hsai);
2015 #else
2016 HAL_SAI_ErrorCallback(hsai);
2017 #endif
2020 if (hsai->hdmarx != NULL)
2022 /* Set the DMA Rx abort callback */
2023 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
2025 /* Abort DMA in IT mode */
2026 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2028 /* Update SAI error code */
2029 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2031 /* Call SAI error callback */
2032 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2033 hsai->ErrorCallback(hsai);
2034 #else
2035 HAL_SAI_ErrorCallback(hsai);
2036 #endif
2040 else
2042 /* Abort SAI */
2043 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
2044 (void) HAL_SAI_Abort(hsai);
2046 /* Set error callback */
2047 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2048 hsai->ErrorCallback(hsai);
2049 #else
2050 HAL_SAI_ErrorCallback(hsai);
2051 #endif
2054 /* SAI WCKCFG interrupt occurred ----------------------------------*/
2055 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
2057 /* Clear the SAI WCKCFG flag */
2058 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
2060 /* Change the SAI error code */
2061 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
2063 /* Check SAI DMA is enabled or not */
2064 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
2066 /* Abort the SAI DMA Streams */
2067 if (hsai->hdmatx != NULL)
2069 /* Set the DMA Tx abort callback */
2070 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
2072 /* Abort DMA in IT mode */
2073 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
2075 /* Update SAI error code */
2076 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2078 /* Call SAI error callback */
2079 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2080 hsai->ErrorCallback(hsai);
2081 #else
2082 HAL_SAI_ErrorCallback(hsai);
2083 #endif
2086 if (hsai->hdmarx != NULL)
2088 /* Set the DMA Rx abort callback */
2089 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
2091 /* Abort DMA in IT mode */
2092 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
2094 /* Update SAI error code */
2095 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2097 /* Call SAI error callback */
2098 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2099 hsai->ErrorCallback(hsai);
2100 #else
2101 HAL_SAI_ErrorCallback(hsai);
2102 #endif
2106 else
2108 /* If WCKCFG occurs, SAI audio block is automatically disabled */
2109 /* Disable all interrupts and clear all flags */
2110 hsai->Instance->IMR = 0U;
2111 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2112 /* Set the SAI state to ready to be able to start again the process */
2113 hsai->State = HAL_SAI_STATE_READY;
2115 /* Initialize XferCount */
2116 hsai->XferCount = 0U;
2118 /* SAI error Callback */
2119 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2120 hsai->ErrorCallback(hsai);
2121 #else
2122 HAL_SAI_ErrorCallback(hsai);
2123 #endif
2126 /* SAI CNRDY interrupt occurred ----------------------------------*/
2127 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
2129 /* Clear the SAI CNRDY flag */
2130 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
2131 /* Change the SAI error code */
2132 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
2133 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
2134 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2135 hsai->ErrorCallback(hsai);
2136 #else
2137 HAL_SAI_ErrorCallback(hsai);
2138 #endif
2140 else
2142 /* Nothing to do */
2148 * @brief Tx Transfer completed callback.
2149 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2150 * the configuration information for SAI module.
2151 * @retval None
2153 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
2155 /* Prevent unused argument(s) compilation warning */
2156 UNUSED(hsai);
2158 /* NOTE : This function should not be modified, when the callback is needed,
2159 the HAL_SAI_TxCpltCallback could be implemented in the user file
2164 * @brief Tx Transfer Half completed callback.
2165 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2166 * the configuration information for SAI module.
2167 * @retval None
2169 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2171 /* Prevent unused argument(s) compilation warning */
2172 UNUSED(hsai);
2174 /* NOTE : This function should not be modified, when the callback is needed,
2175 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2180 * @brief Rx Transfer completed callback.
2181 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2182 * the configuration information for SAI module.
2183 * @retval None
2185 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
2187 /* Prevent unused argument(s) compilation warning */
2188 UNUSED(hsai);
2190 /* NOTE : This function should not be modified, when the callback is needed,
2191 the HAL_SAI_RxCpltCallback could be implemented in the user file
2196 * @brief Rx Transfer half completed callback.
2197 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2198 * the configuration information for SAI module.
2199 * @retval None
2201 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2203 /* Prevent unused argument(s) compilation warning */
2204 UNUSED(hsai);
2206 /* NOTE : This function should not be modified, when the callback is needed,
2207 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2212 * @brief SAI error callback.
2213 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2214 * the configuration information for SAI module.
2215 * @retval None
2217 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
2219 /* Prevent unused argument(s) compilation warning */
2220 UNUSED(hsai);
2222 /* NOTE : This function should not be modified, when the callback is needed,
2223 the HAL_SAI_ErrorCallback could be implemented in the user file
2228 * @}
2231 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2232 * @brief Peripheral State functions
2234 @verbatim
2235 ===============================================================================
2236 ##### Peripheral State and Errors functions #####
2237 ===============================================================================
2238 [..]
2239 This subsection permits to get in run-time the status of the peripheral
2240 and the data flow.
2242 @endverbatim
2243 * @{
2247 * @brief Return the SAI handle state.
2248 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2249 * the configuration information for SAI module.
2250 * @retval HAL state
2252 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
2254 return hsai->State;
2258 * @brief Return the SAI error code.
2259 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2260 * the configuration information for the specified SAI Block.
2261 * @retval SAI Error Code
2263 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
2265 return hsai->ErrorCode;
2269 * @}
2273 * @}
2276 /** @addtogroup SAI_Private_Functions
2277 * @brief Private functions
2278 * @{
2282 * @brief Initialize the SAI I2S protocol according to the specified parameters
2283 * in the SAI_InitTypeDef and create the associated handle.
2284 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2285 * the configuration information for SAI module.
2286 * @param protocol one of the supported protocol.
2287 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2288 * @param nbslot number of slot minimum value is 2 and max is 16.
2289 * the value must be a multiple of 2.
2290 * @retval HAL status
2292 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2294 HAL_StatusTypeDef status = HAL_OK;
2296 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2297 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2298 /* Compute ClockStrobing according AudioMode */
2299 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2301 /* Transmit */
2302 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2304 else
2306 /* Receive */
2307 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2309 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
2310 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2311 hsai->SlotInit.FirstBitOffset = 0;
2312 hsai->SlotInit.SlotNumber = nbslot;
2314 /* in IS2 the number of slot must be even */
2315 if ((nbslot & 0x1U) != 0U)
2317 return HAL_ERROR;
2320 if (protocol == SAI_I2S_STANDARD)
2322 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2323 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2325 else
2327 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2328 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2329 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
2332 /* Frame definition */
2333 switch (datasize)
2335 case SAI_PROTOCOL_DATASIZE_16BIT:
2336 hsai->Init.DataSize = SAI_DATASIZE_16;
2337 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2338 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2339 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2340 break;
2341 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2342 hsai->Init.DataSize = SAI_DATASIZE_16;
2343 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2344 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2345 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2346 break;
2347 case SAI_PROTOCOL_DATASIZE_24BIT:
2348 hsai->Init.DataSize = SAI_DATASIZE_24;
2349 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2350 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2351 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2352 break;
2353 case SAI_PROTOCOL_DATASIZE_32BIT:
2354 hsai->Init.DataSize = SAI_DATASIZE_32;
2355 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2356 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2357 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2358 break;
2359 default :
2360 status = HAL_ERROR;
2361 break;
2363 if (protocol == SAI_I2S_LSBJUSTIFIED)
2365 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2367 hsai->SlotInit.FirstBitOffset = 16;
2369 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2371 hsai->SlotInit.FirstBitOffset = 8;
2374 return status;
2378 * @brief Initialize the SAI PCM protocol according to the specified parameters
2379 * in the SAI_InitTypeDef and create the associated handle.
2380 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2381 * the configuration information for SAI module.
2382 * @param protocol one of the supported protocol
2383 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2384 * @param nbslot number of slot minimum value is 1 and the max is 16.
2385 * @retval HAL status
2387 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2389 HAL_StatusTypeDef status = HAL_OK;
2391 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2392 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2393 /* Compute ClockStrobing according AudioMode */
2394 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2396 /* Transmit */
2397 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2399 else
2401 /* Receive */
2402 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2404 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2405 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2406 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2407 hsai->SlotInit.FirstBitOffset = 0;
2408 hsai->SlotInit.SlotNumber = nbslot;
2409 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2411 if (protocol == SAI_PCM_SHORT)
2413 hsai->FrameInit.ActiveFrameLength = 1;
2415 else
2417 /* SAI_PCM_LONG */
2418 hsai->FrameInit.ActiveFrameLength = 13;
2421 switch (datasize)
2423 case SAI_PROTOCOL_DATASIZE_16BIT:
2424 hsai->Init.DataSize = SAI_DATASIZE_16;
2425 hsai->FrameInit.FrameLength = 16U * nbslot;
2426 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2427 break;
2428 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2429 hsai->Init.DataSize = SAI_DATASIZE_16;
2430 hsai->FrameInit.FrameLength = 32U * nbslot;
2431 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2432 break;
2433 case SAI_PROTOCOL_DATASIZE_24BIT :
2434 hsai->Init.DataSize = SAI_DATASIZE_24;
2435 hsai->FrameInit.FrameLength = 32U * nbslot;
2436 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2437 break;
2438 case SAI_PROTOCOL_DATASIZE_32BIT:
2439 hsai->Init.DataSize = SAI_DATASIZE_32;
2440 hsai->FrameInit.FrameLength = 32U * nbslot;
2441 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2442 break;
2443 default :
2444 status = HAL_ERROR;
2445 break;
2448 return status;
2452 * @brief Fill the fifo.
2453 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2454 * the configuration information for SAI module.
2455 * @retval None
2457 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2459 uint32_t temp;
2461 /* fill the fifo with data before to enabled the SAI */
2462 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2464 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2466 hsai->Instance->DR = *hsai->pBuffPtr;
2467 hsai->pBuffPtr++;
2469 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2471 temp = (uint32_t)(*hsai->pBuffPtr);
2472 hsai->pBuffPtr++;
2473 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2474 hsai->pBuffPtr++;
2475 hsai->Instance->DR = temp;
2477 else
2479 temp = (uint32_t)(*hsai->pBuffPtr);
2480 hsai->pBuffPtr++;
2481 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2482 hsai->pBuffPtr++;
2483 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2484 hsai->pBuffPtr++;
2485 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2486 hsai->pBuffPtr++;
2487 hsai->Instance->DR = temp;
2489 hsai->XferCount--;
2494 * @brief Return the interrupt flag to set according the SAI setup.
2495 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2496 * the configuration information for SAI module.
2497 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2498 * @retval the list of the IT flag to enable
2500 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
2502 uint32_t tmpIT = SAI_IT_OVRUDR;
2504 if (mode == SAI_MODE_IT)
2506 tmpIT |= SAI_IT_FREQ;
2509 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2510 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2512 tmpIT |= SAI_IT_CNRDY;
2515 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2517 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2519 else
2521 /* hsai has been configured in master mode */
2522 tmpIT |= SAI_IT_WCKCFG;
2524 return tmpIT;
2528 * @brief Disable the SAI and wait for the disabling.
2529 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2530 * the configuration information for SAI module.
2531 * @retval None
2533 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2535 uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2536 HAL_StatusTypeDef status = HAL_OK;
2538 /* Disable the SAI instance */
2539 __HAL_SAI_DISABLE(hsai);
2543 /* Check for the Timeout */
2544 if (count == 0U)
2546 /* Update error code */
2547 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2548 status = HAL_TIMEOUT;
2549 break;
2551 count--;
2553 while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
2555 return status;
2559 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2560 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2561 * the configuration information for SAI module.
2562 * @retval None
2564 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2566 if (hsai->XferCount == 0U)
2568 /* Handle the end of the transmission */
2569 /* Disable FREQ and OVRUDR interrupts */
2570 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2571 hsai->State = HAL_SAI_STATE_READY;
2572 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2573 hsai->TxCpltCallback(hsai);
2574 #else
2575 HAL_SAI_TxCpltCallback(hsai);
2576 #endif
2578 else
2580 /* Write data on DR register */
2581 hsai->Instance->DR = *hsai->pBuffPtr;
2582 hsai->pBuffPtr++;
2583 hsai->XferCount--;
2588 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2589 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2590 * the configuration information for SAI module.
2591 * @retval None
2593 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2595 if (hsai->XferCount == 0U)
2597 /* Handle the end of the transmission */
2598 /* Disable FREQ and OVRUDR interrupts */
2599 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2600 hsai->State = HAL_SAI_STATE_READY;
2601 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2602 hsai->TxCpltCallback(hsai);
2603 #else
2604 HAL_SAI_TxCpltCallback(hsai);
2605 #endif
2607 else
2609 /* Write data on DR register */
2610 uint32_t temp;
2611 temp = (uint32_t)(*hsai->pBuffPtr);
2612 hsai->pBuffPtr++;
2613 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2614 hsai->pBuffPtr++;
2615 hsai->Instance->DR = temp;
2616 hsai->XferCount--;
2621 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2622 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2623 * the configuration information for SAI module.
2624 * @retval None
2626 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2628 if (hsai->XferCount == 0U)
2630 /* Handle the end of the transmission */
2631 /* Disable FREQ and OVRUDR interrupts */
2632 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2633 hsai->State = HAL_SAI_STATE_READY;
2634 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2635 hsai->TxCpltCallback(hsai);
2636 #else
2637 HAL_SAI_TxCpltCallback(hsai);
2638 #endif
2640 else
2642 /* Write data on DR register */
2643 uint32_t temp;
2644 temp = (uint32_t)(*hsai->pBuffPtr);
2645 hsai->pBuffPtr++;
2646 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2647 hsai->pBuffPtr++;
2648 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2649 hsai->pBuffPtr++;
2650 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2651 hsai->pBuffPtr++;
2652 hsai->Instance->DR = temp;
2653 hsai->XferCount--;
2658 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2659 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2660 * the configuration information for SAI module.
2661 * @retval None
2663 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2665 /* Receive data */
2666 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
2667 hsai->pBuffPtr++;
2668 hsai->XferCount--;
2670 /* Check end of the transfer */
2671 if (hsai->XferCount == 0U)
2673 /* Disable TXE and OVRUDR interrupts */
2674 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2676 /* Clear the SAI Overrun flag */
2677 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2679 hsai->State = HAL_SAI_STATE_READY;
2680 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2681 hsai->RxCpltCallback(hsai);
2682 #else
2683 HAL_SAI_RxCpltCallback(hsai);
2684 #endif
2689 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2690 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2691 * the configuration information for SAI module.
2692 * @retval None
2694 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2696 uint32_t temp;
2698 /* Receive data */
2699 temp = hsai->Instance->DR;
2700 *hsai->pBuffPtr = (uint8_t)temp;
2701 hsai->pBuffPtr++;
2702 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2703 hsai->pBuffPtr++;
2704 hsai->XferCount--;
2706 /* Check end of the transfer */
2707 if (hsai->XferCount == 0U)
2709 /* Disable TXE and OVRUDR interrupts */
2710 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2712 /* Clear the SAI Overrun flag */
2713 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2715 hsai->State = HAL_SAI_STATE_READY;
2716 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2717 hsai->RxCpltCallback(hsai);
2718 #else
2719 HAL_SAI_RxCpltCallback(hsai);
2720 #endif
2725 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2726 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2727 * the configuration information for SAI module.
2728 * @retval None
2730 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2732 uint32_t temp;
2734 /* Receive data */
2735 temp = hsai->Instance->DR;
2736 *hsai->pBuffPtr = (uint8_t)temp;
2737 hsai->pBuffPtr++;
2738 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2739 hsai->pBuffPtr++;
2740 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
2741 hsai->pBuffPtr++;
2742 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
2743 hsai->pBuffPtr++;
2744 hsai->XferCount--;
2746 /* Check end of the transfer */
2747 if (hsai->XferCount == 0U)
2749 /* Disable TXE and OVRUDR interrupts */
2750 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2752 /* Clear the SAI Overrun flag */
2753 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2755 hsai->State = HAL_SAI_STATE_READY;
2756 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2757 hsai->RxCpltCallback(hsai);
2758 #else
2759 HAL_SAI_RxCpltCallback(hsai);
2760 #endif
2765 * @brief DMA SAI transmit process complete callback.
2766 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2767 * the configuration information for the specified DMA module.
2768 * @retval None
2770 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2772 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2774 if (hdma->Init.Mode != DMA_CIRCULAR)
2776 hsai->XferCount = 0;
2778 /* Disable SAI Tx DMA Request */
2779 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2781 /* Stop the interrupts error handling */
2782 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2784 hsai->State = HAL_SAI_STATE_READY;
2786 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2787 hsai->TxCpltCallback(hsai);
2788 #else
2789 HAL_SAI_TxCpltCallback(hsai);
2790 #endif
2794 * @brief DMA SAI transmit process half complete callback.
2795 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2796 * the configuration information for the specified DMA module.
2797 * @retval None
2799 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2801 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2803 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2804 hsai->TxHalfCpltCallback(hsai);
2805 #else
2806 HAL_SAI_TxHalfCpltCallback(hsai);
2807 #endif
2811 * @brief DMA SAI receive process complete callback.
2812 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2813 * the configuration information for the specified DMA module.
2814 * @retval None
2816 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2818 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2820 if (hdma->Init.Mode != DMA_CIRCULAR)
2822 /* Disable Rx DMA Request */
2823 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2824 hsai->XferCount = 0;
2826 /* Stop the interrupts error handling */
2827 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2829 hsai->State = HAL_SAI_STATE_READY;
2831 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2832 hsai->RxCpltCallback(hsai);
2833 #else
2834 HAL_SAI_RxCpltCallback(hsai);
2835 #endif
2839 * @brief DMA SAI receive process half complete callback
2840 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2841 * the configuration information for the specified DMA module.
2842 * @retval None
2844 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2846 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2848 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2849 hsai->RxHalfCpltCallback(hsai);
2850 #else
2851 HAL_SAI_RxHalfCpltCallback(hsai);
2852 #endif
2856 * @brief DMA SAI communication error callback.
2857 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2858 * the configuration information for the specified DMA module.
2859 * @retval None
2861 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2863 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2865 /* Ignore DMA FIFO error */
2866 if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2868 /* Set SAI error code */
2869 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2871 /* Disable the SAI DMA request */
2872 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2874 /* Disable SAI peripheral */
2875 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2876 (void) SAI_Disable(hsai);
2878 /* Set the SAI state ready to be able to start again the process */
2879 hsai->State = HAL_SAI_STATE_READY;
2881 /* Initialize XferCount */
2882 hsai->XferCount = 0U;
2884 /* SAI error Callback */
2885 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2886 hsai->ErrorCallback(hsai);
2887 #else
2888 HAL_SAI_ErrorCallback(hsai);
2889 #endif
2894 * @brief DMA SAI Abort callback.
2895 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2896 * the configuration information for the specified DMA module.
2897 * @retval None
2899 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2901 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2903 /* Disable DMA request */
2904 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2906 /* Disable all interrupts and clear all flags */
2907 hsai->Instance->IMR = 0U;
2908 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2910 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2912 /* Disable SAI peripheral */
2913 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2914 (void) SAI_Disable(hsai);
2916 /* Flush the fifo */
2917 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2919 /* Set the SAI state to ready to be able to start again the process */
2920 hsai->State = HAL_SAI_STATE_READY;
2922 /* Initialize XferCount */
2923 hsai->XferCount = 0U;
2925 /* SAI error Callback */
2926 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2927 hsai->ErrorCallback(hsai);
2928 #else
2929 HAL_SAI_ErrorCallback(hsai);
2930 #endif
2934 * @}
2937 #endif /* HAL_SAI_MODULE_ENABLED */
2939 * @}
2943 * @}
2946 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/