Merge pull request #11189 from klutvott123/move-telemetry-displayport-init
[betaflight.git] / lib / main / STM32G4 / Drivers / STM32G4xx_HAL_Driver / Src / stm32g4xx_hal_sai.c
blob2d719aa595a24c6ffd6093dcd98d10659885d1fa
1 /**
2 ******************************************************************************
3 * @file stm32g4xx_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 SAI clock source is configured:
52 (+@) SYSCLK or
53 (+@) PLLQ output or
54 (+@) HSI or
55 (+@) External clock source which is configured after setting correctly
56 the define constant EXTERNAL_CLOCK_VALUE in the stm32g4xx_hal_conf.h file.
58 [..]
59 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
60 for the external slaves even if there is no data in the FIFO, However FS signal
61 generation is conditioned by the presence of data in the FIFO.
63 [..]
64 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
65 and FS signal for the external slaves.
67 [..]
68 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
69 (+@) First bit Offset <= (SLOT size - Data size)
70 (+@) Data size <= SLOT size
71 (+@) Number of SLOT x SLOT size = Frame length
72 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
74 [..]
75 (@) PDM interface can be activated through HAL_SAI_Init function.
76 Please note that PDM interface is only available for SAI1 sub-block A.
77 PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
79 [..]
80 Three operation modes are available within this driver :
82 *** Polling mode IO operation ***
83 =================================
84 [..]
85 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
86 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
88 *** Interrupt mode IO operation ***
89 ===================================
90 [..]
91 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
92 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
93 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
94 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
95 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
96 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
97 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
98 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
100 *** DMA mode IO operation ***
101 =============================
102 [..]
103 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
104 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
105 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
106 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
107 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
108 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
109 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
110 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
111 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
112 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
113 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
115 *** SAI HAL driver additional function list ***
116 ===============================================
117 [..]
118 Below the list the others API available SAI HAL driver :
120 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
121 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
122 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
123 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
124 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
125 (+) HAL_SAI_Abort(): Abort the current transfer
127 *** SAI HAL driver macros list ***
128 ==================================
129 [..]
130 Below the list of most used macros in SAI HAL driver :
132 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
133 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
134 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
135 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
136 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
137 enabled or disabled
138 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
140 *** Callback registration ***
141 =============================
143 The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
144 allows the user to configure dynamically the driver callbacks.
145 Use functions @ref HAL_SAI_RegisterCallback() to register a user callback.
147 Function @ref HAL_SAI_RegisterCallback() allows to register following callbacks:
148 (+) RxCpltCallback : SAI receive complete.
149 (+) RxHalfCpltCallback : SAI receive half complete.
150 (+) TxCpltCallback : SAI transmit complete.
151 (+) TxHalfCpltCallback : SAI transmit half complete.
152 (+) ErrorCallback : SAI error.
153 (+) MspInitCallback : SAI MspInit.
154 (+) MspDeInitCallback : SAI MspDeInit.
155 This function takes as parameters the HAL peripheral handle, the callback ID
156 and a pointer to the user callback function.
158 Use function @ref HAL_SAI_UnRegisterCallback() to reset a callback to the default
159 weak (surcharged) function.
160 @ref HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
161 and the callback ID.
162 This function allows to reset following callbacks:
163 (+) RxCpltCallback : SAI receive complete.
164 (+) RxHalfCpltCallback : SAI receive half complete.
165 (+) TxCpltCallback : SAI transmit complete.
166 (+) TxHalfCpltCallback : SAI transmit half complete.
167 (+) ErrorCallback : SAI error.
168 (+) MspInitCallback : SAI MspInit.
169 (+) MspDeInitCallback : SAI MspDeInit.
171 By default, after the @ref HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
172 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
173 examples @ref HAL_SAI_RxCpltCallback(), @ref HAL_SAI_ErrorCallback().
174 Exception done for MspInit and MspDeInit callbacks that are respectively
175 reset to the legacy weak (surcharged) functions in the @ref HAL_SAI_Init
176 and @ref HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
177 If not, MspInit or MspDeInit are not null, the @ref HAL_SAI_Init and @ref HAL_SAI_DeInit
178 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
180 Callbacks can be registered/unregistered in READY state only.
181 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
182 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
183 during the Init/DeInit.
184 In that case first register the MspInit/MspDeInit user callbacks
185 using @ref HAL_SAI_RegisterCallback before calling @ref HAL_SAI_DeInit
186 or @ref HAL_SAI_Init function.
188 When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
189 not defined, the callback registering feature is not available
190 and weak (surcharged) callbacks are used.
192 @endverbatim
193 ******************************************************************************
194 * @attention
196 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
197 * All rights reserved.</center></h2>
199 * This software component is licensed by ST under BSD 3-Clause license,
200 * the "License"; You may not use this file except in compliance with the
201 * License. You may obtain a copy of the License at:
202 * opensource.org/licenses/BSD-3-Clause
204 ******************************************************************************
207 /* Includes ------------------------------------------------------------------*/
208 #include "stm32g4xx_hal.h"
210 /** @addtogroup STM32G4xx_HAL_Driver
211 * @{
214 /** @defgroup SAI SAI
215 * @brief SAI HAL module driver
216 * @{
219 #ifdef HAL_SAI_MODULE_ENABLED
221 /* Private typedef -----------------------------------------------------------*/
222 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
223 * @{
225 typedef enum
227 SAI_MODE_DMA,
228 SAI_MODE_IT
229 } SAI_ModeTypedef;
231 * @}
234 /* Private define ------------------------------------------------------------*/
235 /** @defgroup SAI_Private_Constants SAI Private Constants
236 * @{
238 #define SAI_DEFAULT_TIMEOUT 4U
239 #define SAI_LONG_TIMEOUT 1000U
241 * @}
244 /* Private macro -------------------------------------------------------------*/
245 /* Private variables ---------------------------------------------------------*/
246 /* Private function prototypes -----------------------------------------------*/
247 /** @defgroup SAI_Private_Functions SAI Private Functions
248 * @{
250 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
251 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
252 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
253 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
255 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
256 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
257 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
258 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
259 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
260 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
261 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
263 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
264 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
265 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
266 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
267 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
268 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
270 * @}
273 /* Exported functions ---------------------------------------------------------*/
274 /** @defgroup SAI_Exported_Functions SAI Exported Functions
275 * @{
278 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
279 * @brief Initialization and Configuration functions
281 @verbatim
282 ===============================================================================
283 ##### Initialization and de-initialization functions #####
284 ===============================================================================
285 [..] This subsection provides a set of functions allowing to initialize and
286 de-initialize the SAIx peripheral:
288 (+) User must implement HAL_SAI_MspInit() function in which he configures
289 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
291 (+) Call the function HAL_SAI_Init() to configure the selected device with
292 the selected configuration:
293 (++) Mode (Master/slave TX/RX)
294 (++) Protocol
295 (++) Data Size
296 (++) MCLK Output
297 (++) Audio frequency
298 (++) FIFO Threshold
299 (++) Frame Config
300 (++) Slot Config
301 (++) PDM Config
303 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
304 of the selected SAI peripheral.
306 @endverbatim
307 * @{
311 * @brief Initialize the structure FrameInit, SlotInit and the low part of
312 * Init according to the specified parameters and call the function
313 * HAL_SAI_Init to initialize the SAI block.
314 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
315 * the configuration information for SAI module.
316 * @param protocol one of the supported protocol @ref SAI_Protocol
317 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
318 * the configuration information for SAI module.
319 * @param nbslot Number of slot.
320 * @retval HAL status
322 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
324 HAL_StatusTypeDef status;
326 /* Check the parameters */
327 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
328 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
330 switch (protocol)
332 case SAI_I2S_STANDARD :
333 case SAI_I2S_MSBJUSTIFIED :
334 case SAI_I2S_LSBJUSTIFIED :
335 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
336 break;
337 case SAI_PCM_LONG :
338 case SAI_PCM_SHORT :
339 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
340 break;
341 default :
342 status = HAL_ERROR;
343 break;
346 if (status == HAL_OK)
348 status = HAL_SAI_Init(hsai);
351 return status;
355 * @brief Initialize the SAI according to the specified parameters.
356 * in the SAI_InitTypeDef structure and initialize the associated handle.
357 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
358 * the configuration information for SAI module.
359 * @retval HAL status
361 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
363 uint32_t tmpregisterGCR;
364 uint32_t ckstr_bits;
365 uint32_t syncen_bits;
367 /* Check the SAI handle allocation */
368 if (hsai == NULL)
370 return HAL_ERROR;
373 /* check the instance */
374 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
376 /* Check the SAI Block parameters */
377 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
378 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
379 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
380 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
381 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
382 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
383 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
384 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
385 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
386 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
387 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
388 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
389 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
390 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
391 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
392 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
394 /* Check the SAI Block Frame parameters */
395 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
396 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
397 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
398 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
399 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
401 /* Check the SAI Block Slot parameters */
402 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
403 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
404 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
405 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
407 /* Check the SAI PDM parameters */
408 assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
409 if (hsai->Init.PdmInit.Activation == ENABLE)
411 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
412 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
413 /* Check that SAI sub-block is SAI1 sub-block A, in master RX mode with free protocol */
414 if ((hsai->Instance != SAI1_Block_A) ||
415 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
416 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
418 return HAL_ERROR;
422 if (hsai->State == HAL_SAI_STATE_RESET)
424 /* Allocate lock resource and initialize it */
425 hsai->Lock = HAL_UNLOCKED;
427 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
428 /* Reset callback pointers to the weak predefined callbacks */
429 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
430 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
431 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
432 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
433 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
435 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
436 if (hsai->MspInitCallback == NULL)
438 hsai->MspInitCallback = HAL_SAI_MspInit;
440 hsai->MspInitCallback(hsai);
441 #else
442 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
443 HAL_SAI_MspInit(hsai);
444 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
447 /* Disable the selected SAI peripheral */
448 if (SAI_Disable(hsai) != HAL_OK)
450 return HAL_ERROR;
453 hsai->State = HAL_SAI_STATE_BUSY;
455 /* SAI Block Synchro Configuration -----------------------------------------*/
456 /* This setting must be done with both audio block (A & B) disabled */
457 switch (hsai->Init.SynchroExt)
459 case SAI_SYNCEXT_DISABLE :
460 tmpregisterGCR = 0;
461 break;
462 case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
463 tmpregisterGCR = SAI_GCR_SYNCOUT_0;
464 break;
465 case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
466 tmpregisterGCR = SAI_GCR_SYNCOUT_1;
467 break;
468 default :
469 tmpregisterGCR = 0;
470 break;
473 switch (hsai->Init.Synchro)
475 case SAI_ASYNCHRONOUS :
476 syncen_bits = 0;
477 break;
478 case SAI_SYNCHRONOUS :
479 syncen_bits = SAI_xCR1_SYNCEN_0;
480 break;
481 case SAI_SYNCHRONOUS_EXT_SAI1 :
482 syncen_bits = SAI_xCR1_SYNCEN_1;
483 break;
484 case SAI_SYNCHRONOUS_EXT_SAI2 :
485 syncen_bits = SAI_xCR1_SYNCEN_1;
486 tmpregisterGCR |= SAI_GCR_SYNCIN_0;
487 break;
488 default :
489 syncen_bits = 0;
490 break;
493 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
495 SAI1->GCR = tmpregisterGCR;
498 if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
500 uint32_t freq = 0;
501 uint32_t tmpval;
503 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
504 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
506 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
509 /* Configure Master Clock Divider using the following formula :
510 - If NODIV = 1 :
511 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
512 - If NODIV = 0 :
513 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
514 if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
516 /* NODIV = 1 */
517 /* (freq x 10) to keep Significant digits */
518 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * hsai->FrameInit.FrameLength);
520 else
522 /* NODIV = 0 */
523 uint32_t tmposr;
524 tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
525 /* (freq x 10) to keep Significant digits */
526 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
528 hsai->Init.Mckdiv = tmpval / 10U;
530 /* Round result to the nearest integer */
531 if ((tmpval % 10U) > 8U)
533 hsai->Init.Mckdiv += 1U;
536 /* Check the SAI Block master clock divider parameter */
537 assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
539 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
540 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
542 /* Transmit */
543 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
545 else
547 /* Receive */
548 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
551 /* SAI Block Configuration -------------------------------------------------*/
552 /* SAI CR1 Configuration */
553 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
554 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
555 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
556 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
557 SAI_xCR1_MCKEN);
559 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
560 hsai->Init.DataSize | hsai->Init.FirstBit | \
561 ckstr_bits | syncen_bits | \
562 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
563 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
564 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
566 /* SAI CR2 Configuration */
567 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
568 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
570 /* SAI Frame Configuration -----------------------------------------*/
571 hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
572 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
573 hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
574 hsai->FrameInit.FSOffset |
575 hsai->FrameInit.FSDefinition |
576 hsai->FrameInit.FSPolarity |
577 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
579 /* SAI Block_x SLOT Configuration ------------------------------------------*/
580 /* This register has no meaning in AC 97 and SPDIF audio protocol */
581 hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
582 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
584 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
585 (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8);
587 /* SAI PDM Configuration ---------------------------------------------------*/
588 if (hsai->Instance == SAI1_Block_A)
590 /* Disable PDM interface */
591 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
592 if (hsai->Init.PdmInit.Activation == ENABLE)
594 /* Configure and enable PDM interface */
595 SAI1->PDMCR = (hsai->Init.PdmInit.ClockEnable |
596 ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
597 SAI1->PDMCR |= SAI_PDMCR_PDMEN;
601 /* Initialize the error code */
602 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
604 /* Initialize the SAI state */
605 hsai->State = HAL_SAI_STATE_READY;
607 /* Release Lock */
608 __HAL_UNLOCK(hsai);
610 return HAL_OK;
614 * @brief DeInitialize the SAI peripheral.
615 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
616 * the configuration information for SAI module.
617 * @retval HAL status
619 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
621 /* Check the SAI handle allocation */
622 if (hsai == NULL)
624 return HAL_ERROR;
627 hsai->State = HAL_SAI_STATE_BUSY;
629 /* Disabled All interrupt and clear all the flag */
630 hsai->Instance->IMR = 0;
631 hsai->Instance->CLRFR = 0xFFFFFFFFU;
633 /* Disable the SAI */
634 if (SAI_Disable(hsai) != HAL_OK)
636 /* Reset SAI state to ready */
637 hsai->State = HAL_SAI_STATE_READY;
639 /* Release Lock */
640 __HAL_UNLOCK(hsai);
642 return HAL_ERROR;
645 /* Flush the fifo */
646 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
648 /* Disable SAI PDM interface */
649 if (hsai->Instance == SAI1_Block_A)
651 /* Reset PDM delays */
652 SAI1->PDMDLY = 0U;
654 /* Disable PDM interface */
655 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
658 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
659 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
660 if (hsai->MspDeInitCallback == NULL)
662 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
664 hsai->MspDeInitCallback(hsai);
665 #else
666 HAL_SAI_MspDeInit(hsai);
667 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
669 /* Initialize the error code */
670 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
672 /* Initialize the SAI state */
673 hsai->State = HAL_SAI_STATE_RESET;
675 /* Release Lock */
676 __HAL_UNLOCK(hsai);
678 return HAL_OK;
682 * @brief Initialize the SAI MSP.
683 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
684 * the configuration information for SAI module.
685 * @retval None
687 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
689 /* Prevent unused argument(s) compilation warning */
690 UNUSED(hsai);
692 /* NOTE : This function should not be modified, when the callback is needed,
693 the HAL_SAI_MspInit could be implemented in the user file
698 * @brief DeInitialize the SAI MSP.
699 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
700 * the configuration information for SAI module.
701 * @retval None
703 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
705 /* Prevent unused argument(s) compilation warning */
706 UNUSED(hsai);
708 /* NOTE : This function should not be modified, when the callback is needed,
709 the HAL_SAI_MspDeInit could be implemented in the user file
713 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
715 * @brief Register a user SAI callback
716 * to be used instead of the weak predefined callback.
717 * @param hsai SAI handle.
718 * @param CallbackID ID of the callback to be registered.
719 * This parameter can be one of the following values:
720 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
721 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
722 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
723 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
724 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
725 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
726 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
727 * @param pCallback pointer to the callback function.
728 * @retval HAL status.
730 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
731 HAL_SAI_CallbackIDTypeDef CallbackID,
732 pSAI_CallbackTypeDef pCallback)
734 HAL_StatusTypeDef status = HAL_OK;
736 if (pCallback == NULL)
738 /* update the error code */
739 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
740 /* update return status */
741 status = HAL_ERROR;
743 else
745 if (HAL_SAI_STATE_READY == hsai->State)
747 switch (CallbackID)
749 case HAL_SAI_RX_COMPLETE_CB_ID :
750 hsai->RxCpltCallback = pCallback;
751 break;
752 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
753 hsai->RxHalfCpltCallback = pCallback;
754 break;
755 case HAL_SAI_TX_COMPLETE_CB_ID :
756 hsai->TxCpltCallback = pCallback;
757 break;
758 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
759 hsai->TxHalfCpltCallback = pCallback;
760 break;
761 case HAL_SAI_ERROR_CB_ID :
762 hsai->ErrorCallback = pCallback;
763 break;
764 case HAL_SAI_MSPINIT_CB_ID :
765 hsai->MspInitCallback = pCallback;
766 break;
767 case HAL_SAI_MSPDEINIT_CB_ID :
768 hsai->MspDeInitCallback = pCallback;
769 break;
770 default :
771 /* update the error code */
772 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
773 /* update return status */
774 status = HAL_ERROR;
775 break;
778 else if (HAL_SAI_STATE_RESET == hsai->State)
780 switch (CallbackID)
782 case HAL_SAI_MSPINIT_CB_ID :
783 hsai->MspInitCallback = pCallback;
784 break;
785 case HAL_SAI_MSPDEINIT_CB_ID :
786 hsai->MspDeInitCallback = pCallback;
787 break;
788 default :
789 /* update the error code */
790 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
791 /* update return status */
792 status = HAL_ERROR;
793 break;
796 else
798 /* update the error code */
799 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
800 /* update return status */
801 status = HAL_ERROR;
804 return status;
808 * @brief Unregister a user SAI callback.
809 * SAI callback is redirected to the weak predefined callback.
810 * @param hsai SAI handle.
811 * @param CallbackID ID of the callback to be unregistered.
812 * This parameter can be one of the following values:
813 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
814 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
815 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
816 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
817 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
818 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
819 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
820 * @retval HAL status.
822 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
823 HAL_SAI_CallbackIDTypeDef CallbackID)
825 HAL_StatusTypeDef status = HAL_OK;
827 if (HAL_SAI_STATE_READY == hsai->State)
829 switch (CallbackID)
831 case HAL_SAI_RX_COMPLETE_CB_ID :
832 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
833 break;
834 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
835 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
836 break;
837 case HAL_SAI_TX_COMPLETE_CB_ID :
838 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
839 break;
840 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
841 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
842 break;
843 case HAL_SAI_ERROR_CB_ID :
844 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
845 break;
846 case HAL_SAI_MSPINIT_CB_ID :
847 hsai->MspInitCallback = HAL_SAI_MspInit;
848 break;
849 case HAL_SAI_MSPDEINIT_CB_ID :
850 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
851 break;
852 default :
853 /* update the error code */
854 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
855 /* update return status */
856 status = HAL_ERROR;
857 break;
860 else if (HAL_SAI_STATE_RESET == hsai->State)
862 switch (CallbackID)
864 case HAL_SAI_MSPINIT_CB_ID :
865 hsai->MspInitCallback = HAL_SAI_MspInit;
866 break;
867 case HAL_SAI_MSPDEINIT_CB_ID :
868 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
869 break;
870 default :
871 /* update the error code */
872 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
873 /* update return status */
874 status = HAL_ERROR;
875 break;
878 else
880 /* update the error code */
881 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
882 /* update return status */
883 status = HAL_ERROR;
885 return status;
887 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
890 * @}
893 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
894 * @brief Data transfers functions
896 @verbatim
897 ==============================================================================
898 ##### IO operation functions #####
899 ==============================================================================
900 [..]
901 This subsection provides a set of functions allowing to manage the SAI data
902 transfers.
904 (+) There are two modes of transfer:
905 (++) Blocking mode : The communication is performed in the polling mode.
906 The status of all data processing is returned by the same function
907 after finishing transfer.
908 (++) No-Blocking mode : The communication is performed using Interrupts
909 or DMA. These functions return the status of the transfer startup.
910 The end of the data processing will be indicated through the
911 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
912 using DMA mode.
914 (+) Blocking mode functions are :
915 (++) HAL_SAI_Transmit()
916 (++) HAL_SAI_Receive()
918 (+) Non Blocking mode functions with Interrupt are :
919 (++) HAL_SAI_Transmit_IT()
920 (++) HAL_SAI_Receive_IT()
922 (+) Non Blocking mode functions with DMA are :
923 (++) HAL_SAI_Transmit_DMA()
924 (++) HAL_SAI_Receive_DMA()
926 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
927 (++) HAL_SAI_TxCpltCallback()
928 (++) HAL_SAI_RxCpltCallback()
929 (++) HAL_SAI_ErrorCallback()
931 @endverbatim
932 * @{
936 * @brief Transmit an amount of data in blocking mode.
937 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
938 * the configuration information for SAI module.
939 * @param pData Pointer to data buffer
940 * @param Size Amount of data to be sent
941 * @param Timeout Timeout duration
942 * @retval HAL status
944 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
946 uint32_t tickstart = HAL_GetTick();
947 uint32_t temp;
949 if ((pData == NULL) || (Size == 0U))
951 return HAL_ERROR;
954 if (hsai->State == HAL_SAI_STATE_READY)
956 /* Process Locked */
957 __HAL_LOCK(hsai);
959 hsai->XferSize = Size;
960 hsai->XferCount = Size;
961 hsai->pBuffPtr = pData;
962 hsai->State = HAL_SAI_STATE_BUSY_TX;
963 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
965 /* Check if the SAI is already enabled */
966 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
968 /* fill the fifo with data before to enabled the SAI */
969 SAI_FillFifo(hsai);
970 /* Enable SAI peripheral */
971 __HAL_SAI_ENABLE(hsai);
974 while (hsai->XferCount > 0U)
976 /* Write data if the FIFO is not full */
977 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
979 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
981 hsai->Instance->DR = *hsai->pBuffPtr;
982 hsai->pBuffPtr++;
984 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
986 temp = (uint32_t)(*hsai->pBuffPtr);
987 hsai->pBuffPtr++;
988 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
989 hsai->pBuffPtr++;
990 hsai->Instance->DR = temp;
992 else
994 temp = (uint32_t)(*hsai->pBuffPtr);
995 hsai->pBuffPtr++;
996 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
997 hsai->pBuffPtr++;
998 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
999 hsai->pBuffPtr++;
1000 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
1001 hsai->pBuffPtr++;
1002 hsai->Instance->DR = temp;
1004 hsai->XferCount--;
1006 else
1008 /* Check for the Timeout */
1009 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1011 /* Update error code */
1012 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1014 /* Clear all the flags */
1015 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1017 /* Disable SAI peripheral */
1018 /* No need to check return value because state update, unlock and error return will be performed later */
1019 (void) SAI_Disable(hsai);
1021 /* Flush the fifo */
1022 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1024 /* Change the SAI state */
1025 hsai->State = HAL_SAI_STATE_READY;
1027 /* Process Unlocked */
1028 __HAL_UNLOCK(hsai);
1030 return HAL_ERROR;
1035 hsai->State = HAL_SAI_STATE_READY;
1037 /* Process Unlocked */
1038 __HAL_UNLOCK(hsai);
1040 return HAL_OK;
1042 else
1044 return HAL_BUSY;
1049 * @brief Receive an amount of data in blocking mode.
1050 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1051 * the configuration information for SAI module.
1052 * @param pData Pointer to data buffer
1053 * @param Size Amount of data to be received
1054 * @param Timeout Timeout duration
1055 * @retval HAL status
1057 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1059 uint32_t tickstart = HAL_GetTick();
1060 uint32_t temp;
1062 if ((pData == NULL) || (Size == 0U))
1064 return HAL_ERROR;
1067 if (hsai->State == HAL_SAI_STATE_READY)
1069 /* Process Locked */
1070 __HAL_LOCK(hsai);
1072 hsai->pBuffPtr = pData;
1073 hsai->XferSize = Size;
1074 hsai->XferCount = Size;
1075 hsai->State = HAL_SAI_STATE_BUSY_RX;
1076 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1078 /* Check if the SAI is already enabled */
1079 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1081 /* Enable SAI peripheral */
1082 __HAL_SAI_ENABLE(hsai);
1085 /* Receive data */
1086 while (hsai->XferCount > 0U)
1088 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1090 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1092 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
1093 hsai->pBuffPtr++;
1095 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1097 temp = hsai->Instance->DR;
1098 *hsai->pBuffPtr = (uint8_t)temp;
1099 hsai->pBuffPtr++;
1100 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1101 hsai->pBuffPtr++;
1103 else
1105 temp = hsai->Instance->DR;
1106 *hsai->pBuffPtr = (uint8_t)temp;
1107 hsai->pBuffPtr++;
1108 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1109 hsai->pBuffPtr++;
1110 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
1111 hsai->pBuffPtr++;
1112 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
1113 hsai->pBuffPtr++;
1115 hsai->XferCount--;
1117 else
1119 /* Check for the Timeout */
1120 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1122 /* Update error code */
1123 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1125 /* Clear all the flags */
1126 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1128 /* Disable SAI peripheral */
1129 /* No need to check return value because state update, unlock and error return will be performed later */
1130 (void) SAI_Disable(hsai);
1132 /* Flush the fifo */
1133 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1135 /* Change the SAI state */
1136 hsai->State = HAL_SAI_STATE_READY;
1138 /* Process Unlocked */
1139 __HAL_UNLOCK(hsai);
1141 return HAL_ERROR;
1146 hsai->State = HAL_SAI_STATE_READY;
1148 /* Process Unlocked */
1149 __HAL_UNLOCK(hsai);
1151 return HAL_OK;
1153 else
1155 return HAL_BUSY;
1160 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1161 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1162 * the configuration information for SAI module.
1163 * @param pData Pointer to data buffer
1164 * @param Size Amount of data to be sent
1165 * @retval HAL status
1167 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1169 if ((pData == NULL) || (Size == 0U))
1171 return HAL_ERROR;
1174 if (hsai->State == HAL_SAI_STATE_READY)
1176 /* Process Locked */
1177 __HAL_LOCK(hsai);
1179 hsai->pBuffPtr = pData;
1180 hsai->XferSize = Size;
1181 hsai->XferCount = Size;
1182 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1183 hsai->State = HAL_SAI_STATE_BUSY_TX;
1185 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1187 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1189 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1191 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1193 else
1195 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1198 /* Fill the fifo before starting the communication */
1199 SAI_FillFifo(hsai);
1201 /* Enable FRQ and OVRUDR interrupts */
1202 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1204 /* Check if the SAI is already enabled */
1205 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1207 /* Enable SAI peripheral */
1208 __HAL_SAI_ENABLE(hsai);
1210 /* Process Unlocked */
1211 __HAL_UNLOCK(hsai);
1213 return HAL_OK;
1215 else
1217 return HAL_BUSY;
1222 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1223 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1224 * the configuration information for SAI module.
1225 * @param pData Pointer to data buffer
1226 * @param Size Amount of data to be received
1227 * @retval HAL status
1229 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1231 if ((pData == NULL) || (Size == 0U))
1233 return HAL_ERROR;
1236 if (hsai->State == HAL_SAI_STATE_READY)
1238 /* Process Locked */
1239 __HAL_LOCK(hsai);
1241 hsai->pBuffPtr = pData;
1242 hsai->XferSize = Size;
1243 hsai->XferCount = Size;
1244 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1245 hsai->State = HAL_SAI_STATE_BUSY_RX;
1247 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1249 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1251 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1253 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1255 else
1257 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1260 /* Enable TXE and OVRUDR interrupts */
1261 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1263 /* Check if the SAI is already enabled */
1264 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1266 /* Enable SAI peripheral */
1267 __HAL_SAI_ENABLE(hsai);
1270 /* Process Unlocked */
1271 __HAL_UNLOCK(hsai);
1273 return HAL_OK;
1275 else
1277 return HAL_BUSY;
1282 * @brief Pause the audio stream playing from the Media.
1283 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1284 * the configuration information for SAI module.
1285 * @retval HAL status
1287 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1289 /* Process Locked */
1290 __HAL_LOCK(hsai);
1292 /* Pause the audio file playing by disabling the SAI DMA requests */
1293 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1295 /* Process Unlocked */
1296 __HAL_UNLOCK(hsai);
1298 return HAL_OK;
1302 * @brief Resume the audio stream playing from the Media.
1303 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1304 * the configuration information for SAI module.
1305 * @retval HAL status
1307 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1309 /* Process Locked */
1310 __HAL_LOCK(hsai);
1312 /* Enable the SAI DMA requests */
1313 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1315 /* If the SAI peripheral is still not enabled, enable it */
1316 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1318 /* Enable SAI peripheral */
1319 __HAL_SAI_ENABLE(hsai);
1322 /* Process Unlocked */
1323 __HAL_UNLOCK(hsai);
1325 return HAL_OK;
1329 * @brief Stop the audio stream playing from the Media.
1330 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1331 * the configuration information for SAI module.
1332 * @retval HAL status
1334 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1336 HAL_StatusTypeDef status = HAL_OK;
1338 /* Process Locked */
1339 __HAL_LOCK(hsai);
1341 /* Disable the SAI DMA request */
1342 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1344 /* Abort the SAI Tx DMA Stream */
1345 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1347 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1349 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1350 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1352 status = HAL_ERROR;
1353 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1358 /* Abort the SAI Rx DMA Stream */
1359 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1361 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1363 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1364 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1366 status = HAL_ERROR;
1367 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1372 /* Disable SAI peripheral */
1373 if (SAI_Disable(hsai) != HAL_OK)
1375 status = HAL_ERROR;
1378 /* Flush the fifo */
1379 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1381 /* Set hsai state to ready */
1382 hsai->State = HAL_SAI_STATE_READY;
1384 /* Process Unlocked */
1385 __HAL_UNLOCK(hsai);
1387 return status;
1391 * @brief Abort the current transfer and disable the SAI.
1392 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1393 * the configuration information for SAI module.
1394 * @retval HAL status
1396 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1398 HAL_StatusTypeDef status = HAL_OK;
1400 /* Process Locked */
1401 __HAL_LOCK(hsai);
1403 /* Check SAI DMA is enabled or not */
1404 if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1406 /* Disable the SAI DMA request */
1407 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1409 /* Abort the SAI Tx DMA Stream */
1410 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1412 if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1414 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1415 if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1417 status = HAL_ERROR;
1418 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1423 /* Abort the SAI Rx DMA Stream */
1424 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1426 if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1428 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1429 if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1431 status = HAL_ERROR;
1432 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1438 /* Disabled All interrupt and clear all the flag */
1439 hsai->Instance->IMR = 0;
1440 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1442 /* Disable SAI peripheral */
1443 if (SAI_Disable(hsai) != HAL_OK)
1445 status = HAL_ERROR;
1448 /* Flush the fifo */
1449 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1451 /* Set hsai state to ready */
1452 hsai->State = HAL_SAI_STATE_READY;
1454 /* Process Unlocked */
1455 __HAL_UNLOCK(hsai);
1457 return status;
1461 * @brief Transmit an amount of data in non-blocking mode with DMA.
1462 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1463 * the configuration information for SAI module.
1464 * @param pData Pointer to data buffer
1465 * @param Size Amount of data to be sent
1466 * @retval HAL status
1468 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1470 uint32_t tickstart = HAL_GetTick();
1472 if ((pData == NULL) || (Size == 0U))
1474 return HAL_ERROR;
1477 if (hsai->State == HAL_SAI_STATE_READY)
1479 /* Process Locked */
1480 __HAL_LOCK(hsai);
1482 hsai->pBuffPtr = pData;
1483 hsai->XferSize = Size;
1484 hsai->XferCount = Size;
1485 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1486 hsai->State = HAL_SAI_STATE_BUSY_TX;
1488 /* Set the SAI Tx DMA Half transfer complete callback */
1489 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1491 /* Set the SAI TxDMA transfer complete callback */
1492 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1494 /* Set the DMA error callback */
1495 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1497 /* Set the DMA Tx abort callback */
1498 hsai->hdmatx->XferAbortCallback = NULL;
1500 /* Enable the Tx DMA Stream */
1501 if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1503 __HAL_UNLOCK(hsai);
1504 return HAL_ERROR;
1507 /* Enable the interrupts for error handling */
1508 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1510 /* Enable SAI Tx DMA Request */
1511 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1513 /* Wait untill FIFO is not empty */
1514 while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1516 /* Check for the Timeout */
1517 if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1519 /* Update error code */
1520 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1522 /* Process Unlocked */
1523 __HAL_UNLOCK(hsai);
1525 return HAL_TIMEOUT;
1529 /* Check if the SAI is already enabled */
1530 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1532 /* Enable SAI peripheral */
1533 __HAL_SAI_ENABLE(hsai);
1536 /* Process Unlocked */
1537 __HAL_UNLOCK(hsai);
1539 return HAL_OK;
1541 else
1543 return HAL_BUSY;
1548 * @brief Receive an amount of data in non-blocking mode with DMA.
1549 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1550 * the configuration information for SAI module.
1551 * @param pData Pointer to data buffer
1552 * @param Size Amount of data to be received
1553 * @retval HAL status
1555 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1558 if ((pData == NULL) || (Size == 0U))
1560 return HAL_ERROR;
1563 if (hsai->State == HAL_SAI_STATE_READY)
1565 /* Process Locked */
1566 __HAL_LOCK(hsai);
1568 hsai->pBuffPtr = pData;
1569 hsai->XferSize = Size;
1570 hsai->XferCount = Size;
1571 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1572 hsai->State = HAL_SAI_STATE_BUSY_RX;
1574 /* Set the SAI Rx DMA Half transfer complete callback */
1575 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1577 /* Set the SAI Rx DMA transfer complete callback */
1578 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1580 /* Set the DMA error callback */
1581 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1583 /* Set the DMA Rx abort callback */
1584 hsai->hdmarx->XferAbortCallback = NULL;
1586 /* Enable the Rx DMA Stream */
1587 if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1589 __HAL_UNLOCK(hsai);
1590 return HAL_ERROR;
1593 /* Check if the SAI is already enabled */
1594 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1596 /* Enable SAI peripheral */
1597 __HAL_SAI_ENABLE(hsai);
1600 /* Enable the interrupts for error handling */
1601 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1603 /* Enable SAI Rx DMA Request */
1604 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1606 /* Process Unlocked */
1607 __HAL_UNLOCK(hsai);
1609 return HAL_OK;
1611 else
1613 return HAL_BUSY;
1618 * @brief Enable the Tx mute mode.
1619 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1620 * the configuration information for SAI module.
1621 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1622 * @retval HAL status
1624 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1626 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1628 if (hsai->State != HAL_SAI_STATE_RESET)
1630 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1631 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
1632 return HAL_OK;
1634 return HAL_ERROR;
1638 * @brief Disable the Tx mute mode.
1639 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1640 * the configuration information for SAI module.
1641 * @retval HAL status
1643 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1645 if (hsai->State != HAL_SAI_STATE_RESET)
1647 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1648 return HAL_OK;
1650 return HAL_ERROR;
1654 * @brief Enable the Rx mute detection.
1655 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1656 * the configuration information for SAI module.
1657 * @param callback function called when the mute is detected.
1658 * @param counter number a data before mute detection max 63.
1659 * @retval HAL status
1661 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1663 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1665 if (hsai->State != HAL_SAI_STATE_RESET)
1667 /* set the mute counter */
1668 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1669 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1670 hsai->mutecallback = callback;
1671 /* enable the IT interrupt */
1672 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1673 return HAL_OK;
1675 return HAL_ERROR;
1679 * @brief Disable the Rx mute detection.
1680 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1681 * the configuration information for SAI module.
1682 * @retval HAL status
1684 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1686 if (hsai->State != HAL_SAI_STATE_RESET)
1688 /* set the mutecallback to NULL */
1689 hsai->mutecallback = NULL;
1690 /* enable the IT interrupt */
1691 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1692 return HAL_OK;
1694 return HAL_ERROR;
1698 * @brief Handle SAI interrupt request.
1699 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1700 * the configuration information for SAI module.
1701 * @retval None
1703 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1705 if (hsai->State != HAL_SAI_STATE_RESET)
1707 uint32_t itflags = hsai->Instance->SR;
1708 uint32_t itsources = hsai->Instance->IMR;
1709 uint32_t cr1config = hsai->Instance->CR1;
1710 uint32_t tmperror;
1712 /* SAI Fifo request interrupt occurred -----------------------------------*/
1713 if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1715 hsai->InterruptServiceRoutine(hsai);
1717 /* SAI Overrun error interrupt occurred ----------------------------------*/
1718 else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1720 /* Clear the SAI Overrun flag */
1721 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1722 /* Get the SAI error code */
1723 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1724 /* Change the SAI error code */
1725 hsai->ErrorCode |= tmperror;
1726 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1727 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1728 hsai->ErrorCallback(hsai);
1729 #else
1730 HAL_SAI_ErrorCallback(hsai);
1731 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1733 /* SAI mutedet interrupt occurred ----------------------------------*/
1734 else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1736 /* Clear the SAI mutedet flag */
1737 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1738 /* call the call back function */
1739 if (hsai->mutecallback != NULL)
1741 /* inform the user that an RX mute event has been detected */
1742 hsai->mutecallback();
1745 /* SAI AFSDET interrupt occurred ----------------------------------*/
1746 else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1748 /* Change the SAI error code */
1749 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1751 /* Check SAI DMA is enabled or not */
1752 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1754 /* Abort the SAI DMA Streams */
1755 if (hsai->hdmatx != NULL)
1757 /* Set the DMA Tx abort callback */
1758 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1760 /* Abort DMA in IT mode */
1761 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1763 /* Update SAI error code */
1764 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1766 /* Call SAI error callback */
1767 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1768 hsai->ErrorCallback(hsai);
1769 #else
1770 HAL_SAI_ErrorCallback(hsai);
1771 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1774 if (hsai->hdmarx != NULL)
1776 /* Set the DMA Rx abort callback */
1777 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1779 /* Abort DMA in IT mode */
1780 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1782 /* Update SAI error code */
1783 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1785 /* Call SAI error callback */
1786 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1787 hsai->ErrorCallback(hsai);
1788 #else
1789 HAL_SAI_ErrorCallback(hsai);
1790 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1794 else
1796 /* Abort SAI */
1797 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1798 (void) HAL_SAI_Abort(hsai);
1800 /* Set error callback */
1801 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1802 hsai->ErrorCallback(hsai);
1803 #else
1804 HAL_SAI_ErrorCallback(hsai);
1805 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1808 /* SAI LFSDET interrupt occurred ----------------------------------*/
1809 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1811 /* Change the SAI error code */
1812 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1814 /* Check SAI DMA is enabled or not */
1815 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1817 /* Abort the SAI DMA Streams */
1818 if (hsai->hdmatx != NULL)
1820 /* Set the DMA Tx abort callback */
1821 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1823 /* Abort DMA in IT mode */
1824 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1826 /* Update SAI error code */
1827 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1829 /* Call SAI error callback */
1830 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1831 hsai->ErrorCallback(hsai);
1832 #else
1833 HAL_SAI_ErrorCallback(hsai);
1834 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1837 if (hsai->hdmarx != NULL)
1839 /* Set the DMA Rx abort callback */
1840 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1842 /* Abort DMA in IT mode */
1843 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1845 /* Update SAI error code */
1846 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1848 /* Call SAI error callback */
1849 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1850 hsai->ErrorCallback(hsai);
1851 #else
1852 HAL_SAI_ErrorCallback(hsai);
1853 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1857 else
1859 /* Abort SAI */
1860 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1861 (void) HAL_SAI_Abort(hsai);
1863 /* Set error callback */
1864 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1865 hsai->ErrorCallback(hsai);
1866 #else
1867 HAL_SAI_ErrorCallback(hsai);
1868 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1871 /* SAI WCKCFG interrupt occurred ----------------------------------*/
1872 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1874 /* Change the SAI error code */
1875 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1877 /* Check SAI DMA is enabled or not */
1878 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1880 /* Abort the SAI DMA Streams */
1881 if (hsai->hdmatx != NULL)
1883 /* Set the DMA Tx abort callback */
1884 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1886 /* Abort DMA in IT mode */
1887 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1889 /* Update SAI error code */
1890 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1892 /* Call SAI error callback */
1893 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1894 hsai->ErrorCallback(hsai);
1895 #else
1896 HAL_SAI_ErrorCallback(hsai);
1897 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1900 if (hsai->hdmarx != NULL)
1902 /* Set the DMA Rx abort callback */
1903 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1905 /* Abort DMA in IT mode */
1906 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1908 /* Update SAI error code */
1909 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1911 /* Call SAI error callback */
1912 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1913 hsai->ErrorCallback(hsai);
1914 #else
1915 HAL_SAI_ErrorCallback(hsai);
1916 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1920 else
1922 /* If WCKCFG occurs, SAI audio block is automatically disabled */
1923 /* Disable all interrupts and clear all flags */
1924 hsai->Instance->IMR = 0U;
1925 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1926 /* Set the SAI state to ready to be able to start again the process */
1927 hsai->State = HAL_SAI_STATE_READY;
1929 /* Initialize XferCount */
1930 hsai->XferCount = 0U;
1932 /* SAI error Callback */
1933 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1934 hsai->ErrorCallback(hsai);
1935 #else
1936 HAL_SAI_ErrorCallback(hsai);
1937 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1940 /* SAI CNRDY interrupt occurred ----------------------------------*/
1941 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1943 /* Clear the SAI CNRDY flag */
1944 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1945 /* Change the SAI error code */
1946 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1947 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1948 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1949 hsai->ErrorCallback(hsai);
1950 #else
1951 HAL_SAI_ErrorCallback(hsai);
1952 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1954 else
1956 /* Nothing to do */
1962 * @brief Tx Transfer completed callback.
1963 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1964 * the configuration information for SAI module.
1965 * @retval None
1967 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1969 /* Prevent unused argument(s) compilation warning */
1970 UNUSED(hsai);
1972 /* NOTE : This function should not be modified, when the callback is needed,
1973 the HAL_SAI_TxCpltCallback could be implemented in the user file
1978 * @brief Tx Transfer Half completed callback.
1979 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1980 * the configuration information for SAI module.
1981 * @retval None
1983 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1985 /* Prevent unused argument(s) compilation warning */
1986 UNUSED(hsai);
1988 /* NOTE : This function should not be modified, when the callback is needed,
1989 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1994 * @brief Rx Transfer completed callback.
1995 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1996 * the configuration information for SAI module.
1997 * @retval None
1999 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
2001 /* Prevent unused argument(s) compilation warning */
2002 UNUSED(hsai);
2004 /* NOTE : This function should not be modified, when the callback is needed,
2005 the HAL_SAI_RxCpltCallback could be implemented in the user file
2010 * @brief Rx Transfer half completed callback.
2011 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2012 * the configuration information for SAI module.
2013 * @retval None
2015 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2017 /* Prevent unused argument(s) compilation warning */
2018 UNUSED(hsai);
2020 /* NOTE : This function should not be modified, when the callback is needed,
2021 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2026 * @brief SAI error callback.
2027 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2028 * the configuration information for SAI module.
2029 * @retval None
2031 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
2033 /* Prevent unused argument(s) compilation warning */
2034 UNUSED(hsai);
2036 /* NOTE : This function should not be modified, when the callback is needed,
2037 the HAL_SAI_ErrorCallback could be implemented in the user file
2042 * @}
2045 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2046 * @brief Peripheral State functions
2048 @verbatim
2049 ===============================================================================
2050 ##### Peripheral State and Errors functions #####
2051 ===============================================================================
2052 [..]
2053 This subsection permits to get in run-time the status of the peripheral
2054 and the data flow.
2056 @endverbatim
2057 * @{
2061 * @brief Return the SAI handle state.
2062 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2063 * the configuration information for SAI module.
2064 * @retval HAL state
2066 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
2068 return hsai->State;
2072 * @brief Return the SAI error code.
2073 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2074 * the configuration information for the specified SAI Block.
2075 * @retval SAI Error Code
2077 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
2079 return hsai->ErrorCode;
2083 * @}
2087 * @}
2090 /** @addtogroup SAI_Private_Functions
2091 * @brief Private functions
2092 * @{
2096 * @brief Initialize the SAI I2S protocol according to the specified parameters
2097 * in the SAI_InitTypeDef and create the associated handle.
2098 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2099 * the configuration information for SAI module.
2100 * @param protocol one of the supported protocol.
2101 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2102 * @param nbslot number of slot minimum value is 2 and max is 16.
2103 * the value must be a multiple of 2.
2104 * @retval HAL status
2106 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2108 HAL_StatusTypeDef status = HAL_OK;
2110 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2111 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2112 /* Compute ClockStrobing according AudioMode */
2113 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2115 /* Transmit */
2116 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2118 else
2120 /* Receive */
2121 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2123 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
2124 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2125 hsai->SlotInit.FirstBitOffset = 0;
2126 hsai->SlotInit.SlotNumber = nbslot;
2128 /* in IS2 the number of slot must be even */
2129 if ((nbslot & 0x1U) != 0U)
2131 return HAL_ERROR;
2134 switch (protocol)
2136 case SAI_I2S_STANDARD :
2137 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2138 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2139 break;
2140 case SAI_I2S_MSBJUSTIFIED :
2141 case SAI_I2S_LSBJUSTIFIED :
2142 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2143 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
2144 break;
2145 default :
2146 status = HAL_ERROR;
2147 break;
2150 /* Frame definition */
2151 switch (datasize)
2153 case SAI_PROTOCOL_DATASIZE_16BIT:
2154 hsai->Init.DataSize = SAI_DATASIZE_16;
2155 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2156 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2157 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2158 break;
2159 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2160 hsai->Init.DataSize = SAI_DATASIZE_16;
2161 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2162 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2163 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2164 break;
2165 case SAI_PROTOCOL_DATASIZE_24BIT:
2166 hsai->Init.DataSize = SAI_DATASIZE_24;
2167 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2168 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2169 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2170 break;
2171 case SAI_PROTOCOL_DATASIZE_32BIT:
2172 hsai->Init.DataSize = SAI_DATASIZE_32;
2173 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2174 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2175 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2176 break;
2177 default :
2178 status = HAL_ERROR;
2179 break;
2181 if (protocol == SAI_I2S_LSBJUSTIFIED)
2183 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2185 hsai->SlotInit.FirstBitOffset = 16;
2187 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2189 hsai->SlotInit.FirstBitOffset = 8;
2192 return status;
2196 * @brief Initialize the SAI PCM protocol according to the specified parameters
2197 * in the SAI_InitTypeDef and create the associated handle.
2198 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2199 * the configuration information for SAI module.
2200 * @param protocol one of the supported protocol
2201 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2202 * @param nbslot number of slot minimum value is 1 and the max is 16.
2203 * @retval HAL status
2205 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2207 HAL_StatusTypeDef status = HAL_OK;
2209 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2210 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2211 /* Compute ClockStrobing according AudioMode */
2212 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2214 /* Transmit */
2215 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2217 else
2219 /* Receive */
2220 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2222 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2223 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2224 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2225 hsai->SlotInit.FirstBitOffset = 0;
2226 hsai->SlotInit.SlotNumber = nbslot;
2227 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2229 switch (protocol)
2231 case SAI_PCM_SHORT :
2232 hsai->FrameInit.ActiveFrameLength = 1;
2233 break;
2234 case SAI_PCM_LONG :
2235 hsai->FrameInit.ActiveFrameLength = 13;
2236 break;
2237 default :
2238 status = HAL_ERROR;
2239 break;
2242 switch (datasize)
2244 case SAI_PROTOCOL_DATASIZE_16BIT:
2245 hsai->Init.DataSize = SAI_DATASIZE_16;
2246 hsai->FrameInit.FrameLength = 16U * nbslot;
2247 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2248 break;
2249 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2250 hsai->Init.DataSize = SAI_DATASIZE_16;
2251 hsai->FrameInit.FrameLength = 32U * nbslot;
2252 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2253 break;
2254 case SAI_PROTOCOL_DATASIZE_24BIT :
2255 hsai->Init.DataSize = SAI_DATASIZE_24;
2256 hsai->FrameInit.FrameLength = 32U * nbslot;
2257 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2258 break;
2259 case SAI_PROTOCOL_DATASIZE_32BIT:
2260 hsai->Init.DataSize = SAI_DATASIZE_32;
2261 hsai->FrameInit.FrameLength = 32U * nbslot;
2262 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2263 break;
2264 default :
2265 status = HAL_ERROR;
2266 break;
2269 return status;
2273 * @brief Fill the fifo.
2274 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2275 * the configuration information for SAI module.
2276 * @retval None
2278 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2280 uint32_t temp;
2282 /* fill the fifo with data before to enabled the SAI */
2283 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2285 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2287 hsai->Instance->DR = *hsai->pBuffPtr;
2288 hsai->pBuffPtr++;
2290 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2292 temp = (uint32_t)(*hsai->pBuffPtr);
2293 hsai->pBuffPtr++;
2294 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2295 hsai->pBuffPtr++;
2296 hsai->Instance->DR = temp;
2298 else
2300 temp = (uint32_t)(*hsai->pBuffPtr);
2301 hsai->pBuffPtr++;
2302 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2303 hsai->pBuffPtr++;
2304 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2305 hsai->pBuffPtr++;
2306 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2307 hsai->pBuffPtr++;
2308 hsai->Instance->DR = temp;
2310 hsai->XferCount--;
2315 * @brief Return the interrupt flag to set according the SAI setup.
2316 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2317 * the configuration information for SAI module.
2318 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2319 * @retval the list of the IT flag to enable
2321 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
2323 uint32_t tmpIT = SAI_IT_OVRUDR;
2325 if (mode == SAI_MODE_IT)
2327 tmpIT |= SAI_IT_FREQ;
2330 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2331 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2333 tmpIT |= SAI_IT_CNRDY;
2336 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2338 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2340 else
2342 /* hsai has been configured in master mode */
2343 tmpIT |= SAI_IT_WCKCFG;
2345 return tmpIT;
2349 * @brief Disable the SAI and wait for the disabling.
2350 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2351 * the configuration information for SAI module.
2352 * @retval None
2354 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2356 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2357 HAL_StatusTypeDef status = HAL_OK;
2359 /* Disable the SAI instance */
2360 __HAL_SAI_DISABLE(hsai);
2364 /* Check for the Timeout */
2365 if (count == 0U)
2367 /* Update error code */
2368 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2369 status = HAL_TIMEOUT;
2370 break;
2372 count--;
2373 } while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
2375 return status;
2379 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2380 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2381 * the configuration information for SAI module.
2382 * @retval None
2384 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2386 if (hsai->XferCount == 0U)
2388 /* Handle the end of the transmission */
2389 /* Disable FREQ and OVRUDR interrupts */
2390 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2391 hsai->State = HAL_SAI_STATE_READY;
2392 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2393 hsai->TxCpltCallback(hsai);
2394 #else
2395 HAL_SAI_TxCpltCallback(hsai);
2396 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2398 else
2400 /* Write data on DR register */
2401 hsai->Instance->DR = *hsai->pBuffPtr;
2402 hsai->pBuffPtr++;
2403 hsai->XferCount--;
2408 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2409 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2410 * the configuration information for SAI module.
2411 * @retval None
2413 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2415 if (hsai->XferCount == 0U)
2417 /* Handle the end of the transmission */
2418 /* Disable FREQ and OVRUDR interrupts */
2419 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2420 hsai->State = HAL_SAI_STATE_READY;
2421 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2422 hsai->TxCpltCallback(hsai);
2423 #else
2424 HAL_SAI_TxCpltCallback(hsai);
2425 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2427 else
2429 /* Write data on DR register */
2430 uint32_t temp;
2431 temp = (uint32_t)(*hsai->pBuffPtr);
2432 hsai->pBuffPtr++;
2433 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2434 hsai->pBuffPtr++;
2435 hsai->Instance->DR = temp;
2436 hsai->XferCount--;
2441 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2442 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2443 * the configuration information for SAI module.
2444 * @retval None
2446 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2448 if (hsai->XferCount == 0U)
2450 /* Handle the end of the transmission */
2451 /* Disable FREQ and OVRUDR interrupts */
2452 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2453 hsai->State = HAL_SAI_STATE_READY;
2454 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2455 hsai->TxCpltCallback(hsai);
2456 #else
2457 HAL_SAI_TxCpltCallback(hsai);
2458 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2460 else
2462 /* Write data on DR register */
2463 uint32_t temp;
2464 temp = (uint32_t)(*hsai->pBuffPtr);
2465 hsai->pBuffPtr++;
2466 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2467 hsai->pBuffPtr++;
2468 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2469 hsai->pBuffPtr++;
2470 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2471 hsai->pBuffPtr++;
2472 hsai->Instance->DR = temp;
2473 hsai->XferCount--;
2478 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2479 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2480 * the configuration information for SAI module.
2481 * @retval None
2483 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2485 /* Receive data */
2486 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
2487 hsai->pBuffPtr++;
2488 hsai->XferCount--;
2490 /* Check end of the transfer */
2491 if (hsai->XferCount == 0U)
2493 /* Disable TXE and OVRUDR interrupts */
2494 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2496 /* Clear the SAI Overrun flag */
2497 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2499 hsai->State = HAL_SAI_STATE_READY;
2500 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2501 hsai->RxCpltCallback(hsai);
2502 #else
2503 HAL_SAI_RxCpltCallback(hsai);
2504 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2509 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2510 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2511 * the configuration information for SAI module.
2512 * @retval None
2514 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2516 uint32_t temp;
2518 /* Receive data */
2519 temp = hsai->Instance->DR;
2520 *hsai->pBuffPtr = (uint8_t)temp;
2521 hsai->pBuffPtr++;
2522 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2523 hsai->pBuffPtr++;
2524 hsai->XferCount--;
2526 /* Check end of the transfer */
2527 if (hsai->XferCount == 0U)
2529 /* Disable TXE and OVRUDR interrupts */
2530 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2532 /* Clear the SAI Overrun flag */
2533 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2535 hsai->State = HAL_SAI_STATE_READY;
2536 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2537 hsai->RxCpltCallback(hsai);
2538 #else
2539 HAL_SAI_RxCpltCallback(hsai);
2540 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2545 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2546 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2547 * the configuration information for SAI module.
2548 * @retval None
2550 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2552 uint32_t temp;
2554 /* Receive data */
2555 temp = hsai->Instance->DR;
2556 *hsai->pBuffPtr = (uint8_t)temp;
2557 hsai->pBuffPtr++;
2558 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2559 hsai->pBuffPtr++;
2560 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
2561 hsai->pBuffPtr++;
2562 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
2563 hsai->pBuffPtr++;
2564 hsai->XferCount--;
2566 /* Check end of the transfer */
2567 if (hsai->XferCount == 0U)
2569 /* Disable TXE and OVRUDR interrupts */
2570 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2572 /* Clear the SAI Overrun flag */
2573 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2575 hsai->State = HAL_SAI_STATE_READY;
2576 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2577 hsai->RxCpltCallback(hsai);
2578 #else
2579 HAL_SAI_RxCpltCallback(hsai);
2580 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2585 * @brief DMA SAI transmit process complete callback.
2586 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2587 * the configuration information for the specified DMA module.
2588 * @retval None
2590 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2592 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2594 if (hdma->Init.Mode != DMA_CIRCULAR)
2596 hsai->XferCount = 0;
2598 /* Disable SAI Tx DMA Request */
2599 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2601 /* Stop the interrupts error handling */
2602 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2604 hsai->State = HAL_SAI_STATE_READY;
2606 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2607 hsai->TxCpltCallback(hsai);
2608 #else
2609 HAL_SAI_TxCpltCallback(hsai);
2610 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2614 * @brief DMA SAI transmit process half complete callback.
2615 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2616 * the configuration information for the specified DMA module.
2617 * @retval None
2619 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2621 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2623 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2624 hsai->TxHalfCpltCallback(hsai);
2625 #else
2626 HAL_SAI_TxHalfCpltCallback(hsai);
2627 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2631 * @brief DMA SAI receive process complete callback.
2632 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2633 * the configuration information for the specified DMA module.
2634 * @retval None
2636 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2638 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2640 if (hdma->Init.Mode != DMA_CIRCULAR)
2642 /* Disable Rx DMA Request */
2643 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2644 hsai->XferCount = 0;
2646 /* Stop the interrupts error handling */
2647 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2649 hsai->State = HAL_SAI_STATE_READY;
2651 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2652 hsai->RxCpltCallback(hsai);
2653 #else
2654 HAL_SAI_RxCpltCallback(hsai);
2655 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2659 * @brief DMA SAI receive process half complete callback
2660 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2661 * the configuration information for the specified DMA module.
2662 * @retval None
2664 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2666 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2668 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2669 hsai->RxHalfCpltCallback(hsai);
2670 #else
2671 HAL_SAI_RxHalfCpltCallback(hsai);
2672 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2676 * @brief DMA SAI communication error callback.
2677 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2678 * the configuration information for the specified DMA module.
2679 * @retval None
2681 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2683 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2685 /* Set SAI error code */
2686 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2688 /* Disable the SAI DMA request */
2689 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2691 /* Disable SAI peripheral */
2692 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2693 (void) SAI_Disable(hsai);
2695 /* Set the SAI state ready to be able to start again the process */
2696 hsai->State = HAL_SAI_STATE_READY;
2698 /* Initialize XferCount */
2699 hsai->XferCount = 0U;
2701 /* SAI error Callback */
2702 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2703 hsai->ErrorCallback(hsai);
2704 #else
2705 HAL_SAI_ErrorCallback(hsai);
2706 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2710 * @brief DMA SAI Abort callback.
2711 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2712 * the configuration information for the specified DMA module.
2713 * @retval None
2715 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2717 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2719 /* Disable DMA request */
2720 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2722 /* Disable all interrupts and clear all flags */
2723 hsai->Instance->IMR = 0U;
2724 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2726 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2728 /* Disable SAI peripheral */
2729 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2730 (void) SAI_Disable(hsai);
2732 /* Flush the fifo */
2733 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2735 /* Set the SAI state to ready to be able to start again the process */
2736 hsai->State = HAL_SAI_STATE_READY;
2738 /* Initialize XferCount */
2739 hsai->XferCount = 0U;
2741 /* SAI error Callback */
2742 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2743 hsai->ErrorCallback(hsai);
2744 #else
2745 HAL_SAI_ErrorCallback(hsai);
2746 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2750 * @}
2753 #endif /* HAL_SAI_MODULE_ENABLED */
2755 * @}
2759 * @}
2762 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/