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
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2019 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28
29 [..]
30 The SAI HAL driver can be used as follows:
31
32 (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
33 (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
34 (##) Enable the SAI interface clock.
35 (##) SAI pins configuration:
36 (+++) Enable the clock for the SAI GPIOs.
37 (+++) Configure these SAI pins as alternate function pull-up.
38 (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
39 and HAL_SAI_Receive_IT() APIs):
40 (+++) Configure the SAI interrupt priority.
41 (+++) Enable the NVIC SAI IRQ handle.
42
43 (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
44 and HAL_SAI_Receive_DMA() APIs):
45 (+++) Declare a DMA handle structure for the Tx/Rx stream.
46 (+++) Enable the DMAx interface clock.
47 (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
48 (+++) Configure the DMA Tx/Rx Stream.
49 (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle.
50 (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
51 DMA Tx/Rx Stream.
52
53 (#) The initialization can be done by two ways
54 (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
55 (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
56
57 [..]
58 (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
59 will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
60 inside the transmit and receive process.
61 [..]
62 (@) Make sure that SAI clock source is configured:
63 (+@) SYSCLK or
64 (+@) PLLQ output or
65 (+@) HSI or
66 (+@) External clock source which is configured after setting correctly
67 the define constant EXTERNAL_CLOCK_VALUE in the stm32g4xx_hal_conf.h file.
68
69 [..]
70 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
71 for the external slaves even if there is no data in the FIFO, However FS signal
72 generation is conditioned by the presence of data in the FIFO.
73
74 [..]
75 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
76 and FS signal for the external slaves.
77
78 [..]
79 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
80 (+@) First bit Offset <= (SLOT size - Data size)
81 (+@) Data size <= SLOT size
82 (+@) Number of SLOT x SLOT size = Frame length
83 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
84
85 [..]
86 (@) PDM interface can be activated through HAL_SAI_Init function.
87 Please note that PDM interface is only available for SAI1 sub-block A.
88 PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
89
90 [..]
91 Three operation modes are available within this driver :
92
93 *** Polling mode IO operation ***
94 =================================
95 [..]
96 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
97 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
98
99 *** Interrupt mode IO operation ***
100 ===================================
101 [..]
102 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
103 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
104 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
105 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
106 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
107 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
108 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
109 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
110
111 *** DMA mode IO operation ***
112 =============================
113 [..]
114 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
115 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
116 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
117 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
118 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
119 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
120 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
121 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
122 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
123 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
124 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
125
126 *** SAI HAL driver additional function list ***
127 ===============================================
128 [..]
129 Below the list the others API available SAI HAL driver :
130
131 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
132 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
133 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
134 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
135 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
136 (+) HAL_SAI_Abort(): Abort the current transfer
137
138 *** SAI HAL driver macros list ***
139 ==================================
140 [..]
141 Below the list of most used macros in SAI HAL driver :
142
143 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
144 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
145 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
146 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
147 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
148 enabled or disabled
149 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
150
151 *** Callback registration ***
152 =============================
153 [..]
154 The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
155 allows the user to configure dynamically the driver callbacks.
156 Use functions HAL_SAI_RegisterCallback() to register a user callback.
157
158 [..]
159 Function HAL_SAI_RegisterCallback() allows to register following callbacks:
160 (+) RxCpltCallback : SAI receive complete.
161 (+) RxHalfCpltCallback : SAI receive half complete.
162 (+) TxCpltCallback : SAI transmit complete.
163 (+) TxHalfCpltCallback : SAI transmit half complete.
164 (+) ErrorCallback : SAI error.
165 (+) MspInitCallback : SAI MspInit.
166 (+) MspDeInitCallback : SAI MspDeInit.
167 [..]
168 This function takes as parameters the HAL peripheral handle, the callback ID
169 and a pointer to the user callback function.
170
171 [..]
172 Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
173 weak (surcharged) function.
174 HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
175 and the callback ID.
176 [..]
177 This function allows to reset following callbacks:
178 (+) RxCpltCallback : SAI receive complete.
179 (+) RxHalfCpltCallback : SAI receive half complete.
180 (+) TxCpltCallback : SAI transmit complete.
181 (+) TxHalfCpltCallback : SAI transmit half complete.
182 (+) ErrorCallback : SAI error.
183 (+) MspInitCallback : SAI MspInit.
184 (+) MspDeInitCallback : SAI MspDeInit.
185
186 [..]
187 By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
188 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
189 examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
190 Exception done for MspInit and MspDeInit callbacks that are respectively
191 reset to the legacy weak (surcharged) functions in the HAL_SAI_Init
192 and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
193 If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
194 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
195
196 [..]
197 Callbacks can be registered/unregistered in READY state only.
198 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
199 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
200 during the Init/DeInit.
201 In that case first register the MspInit/MspDeInit user callbacks
202 using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
203 or HAL_SAI_Init function.
204
205 [..]
206 When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
207 not defined, the callback registering feature is not available
208 and weak (surcharged) callbacks are used.
209
210 @endverbatim
211 */
212
213 /* Includes ------------------------------------------------------------------*/
214 #include "stm32g4xx_hal.h"
215
216 /** @addtogroup STM32G4xx_HAL_Driver
217 * @{
218 */
219
220 /** @defgroup SAI SAI
221 * @brief SAI HAL module driver
222 * @{
223 */
224
225 #ifdef HAL_SAI_MODULE_ENABLED
226
227 /* Private typedef -----------------------------------------------------------*/
228 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
229 * @{
230 */
231 typedef enum
232 {
233 SAI_MODE_DMA,
234 SAI_MODE_IT
235 } SAI_ModeTypedef;
236 /**
237 * @}
238 */
239
240 /* Private define ------------------------------------------------------------*/
241 /** @defgroup SAI_Private_Constants SAI Private Constants
242 * @{
243 */
244 #define SAI_DEFAULT_TIMEOUT 4U
245 #define SAI_LONG_TIMEOUT 1000U
246 /**
247 * @}
248 */
249
250 /* Private macro -------------------------------------------------------------*/
251 /* Private variables ---------------------------------------------------------*/
252 /* Private function prototypes -----------------------------------------------*/
253 /** @defgroup SAI_Private_Functions SAI Private Functions
254 * @{
255 */
256 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
257 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
258 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
259 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
260
261 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
262 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
263 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
264 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
265 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
266 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
267 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
268
269 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
270 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
271 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
272 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
273 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
274 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
275 /**
276 * @}
277 */
278
279 /* Exported functions ---------------------------------------------------------*/
280 /** @defgroup SAI_Exported_Functions SAI Exported Functions
281 * @{
282 */
283
284 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
285 * @brief Initialization and Configuration functions
286 *
287 @verbatim
288 ===============================================================================
289 ##### Initialization and de-initialization functions #####
290 ===============================================================================
291 [..] This subsection provides a set of functions allowing to initialize and
292 de-initialize the SAIx peripheral:
293
294 (+) User must implement HAL_SAI_MspInit() function in which he configures
295 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
296
297 (+) Call the function HAL_SAI_Init() to configure the selected device with
298 the selected configuration:
299 (++) Mode (Master/slave TX/RX)
300 (++) Protocol
301 (++) Data Size
302 (++) MCLK Output
303 (++) Audio frequency
304 (++) FIFO Threshold
305 (++) Frame Config
306 (++) Slot Config
307 (++) PDM Config
308
309 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
310 of the selected SAI peripheral.
311
312 @endverbatim
313 * @{
314 */
315
316 /**
317 * @brief Initialize the structure FrameInit, SlotInit and the low part of
318 * Init according to the specified parameters and call the function
319 * HAL_SAI_Init to initialize the SAI block.
320 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
321 * the configuration information for SAI module.
322 * @param protocol one of the supported protocol @ref SAI_Protocol
323 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
324 * the configuration information for SAI module.
325 * @param nbslot Number of slot.
326 * @retval HAL status
327 */
HAL_SAI_InitProtocol(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)328 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
329 {
330 HAL_StatusTypeDef status;
331
332 /* Check the parameters */
333 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
334 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
335
336 switch (protocol)
337 {
338 case SAI_I2S_STANDARD :
339 case SAI_I2S_MSBJUSTIFIED :
340 case SAI_I2S_LSBJUSTIFIED :
341 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
342 break;
343 case SAI_PCM_LONG :
344 case SAI_PCM_SHORT :
345 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
346 break;
347 default :
348 status = HAL_ERROR;
349 break;
350 }
351
352 if (status == HAL_OK)
353 {
354 status = HAL_SAI_Init(hsai);
355 }
356
357 return status;
358 }
359
360 /**
361 * @brief Initialize the SAI according to the specified parameters.
362 * in the SAI_InitTypeDef structure and initialize the associated handle.
363 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
364 * the configuration information for SAI module.
365 * @retval HAL status
366 */
HAL_SAI_Init(SAI_HandleTypeDef * hsai)367 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
368 {
369 uint32_t tmpregisterGCR;
370 uint32_t ckstr_bits;
371 uint32_t syncen_bits;
372
373 /* Check the SAI handle allocation */
374 if (hsai == NULL)
375 {
376 return HAL_ERROR;
377 }
378
379 /* check the instance */
380 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
381
382 /* Check the SAI Block parameters */
383 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
384 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
385 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
386 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
387 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
388 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
389 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
390 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
391 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
392 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
393 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
394 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
395 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
396 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
397 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
398 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
399
400 /* Check the SAI Block Frame parameters */
401 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
402 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
403 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
404 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
405 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
406
407 /* Check the SAI Block Slot parameters */
408 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
409 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
410 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
411 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
412
413 /* Check the SAI PDM parameters */
414 assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
415 if (hsai->Init.PdmInit.Activation == ENABLE)
416 {
417 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
418 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
419 /* Check that SAI sub-block is SAI1 sub-block A, in master RX mode with free protocol */
420 if ((hsai->Instance != SAI1_Block_A) ||
421 (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
422 (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
423 {
424 return HAL_ERROR;
425 }
426 }
427
428 if (hsai->State == HAL_SAI_STATE_RESET)
429 {
430 /* Allocate lock resource and initialize it */
431 hsai->Lock = HAL_UNLOCKED;
432
433 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
434 /* Reset callback pointers to the weak predefined callbacks */
435 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
436 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
437 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
438 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
439 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
440
441 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
442 if (hsai->MspInitCallback == NULL)
443 {
444 hsai->MspInitCallback = HAL_SAI_MspInit;
445 }
446 hsai->MspInitCallback(hsai);
447 #else
448 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
449 HAL_SAI_MspInit(hsai);
450 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
451 }
452
453 /* Disable the selected SAI peripheral */
454 if (SAI_Disable(hsai) != HAL_OK)
455 {
456 return HAL_ERROR;
457 }
458
459 hsai->State = HAL_SAI_STATE_BUSY;
460
461 /* SAI Block Synchro Configuration -----------------------------------------*/
462 /* This setting must be done with both audio block (A & B) disabled */
463 switch (hsai->Init.SynchroExt)
464 {
465 case SAI_SYNCEXT_DISABLE :
466 tmpregisterGCR = 0;
467 break;
468 case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
469 tmpregisterGCR = SAI_GCR_SYNCOUT_0;
470 break;
471 case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
472 tmpregisterGCR = SAI_GCR_SYNCOUT_1;
473 break;
474 default :
475 tmpregisterGCR = 0;
476 break;
477 }
478
479 switch (hsai->Init.Synchro)
480 {
481 case SAI_ASYNCHRONOUS :
482 syncen_bits = 0;
483 break;
484 case SAI_SYNCHRONOUS :
485 syncen_bits = SAI_xCR1_SYNCEN_0;
486 break;
487 case SAI_SYNCHRONOUS_EXT_SAI1 :
488 syncen_bits = SAI_xCR1_SYNCEN_1;
489 break;
490 case SAI_SYNCHRONOUS_EXT_SAI2 :
491 syncen_bits = SAI_xCR1_SYNCEN_1;
492 tmpregisterGCR |= SAI_GCR_SYNCIN_0;
493 break;
494 default :
495 syncen_bits = 0;
496 break;
497 }
498
499 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
500 {
501 SAI1->GCR = tmpregisterGCR;
502 }
503
504 if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
505 {
506 uint32_t freq = 0;
507 uint32_t tmpval;
508
509 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
510 if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
511 {
512 freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
513 }
514
515 /* Configure Master Clock Divider using the following formula :
516 - If NODIV = 1 :
517 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
518 - If NODIV = 0 :
519 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
520 if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
521 {
522 /* NODIV = 1 */
523 uint32_t tmpframelength;
524
525 if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
526 {
527 /* For SPDIF protocol, frame length is set by hardware to 64 */
528 tmpframelength = 64U;
529 }
530 else if (hsai->Init.Protocol == SAI_AC97_PROTOCOL)
531 {
532 /* For AC97 protocol, frame length is set by hardware to 256 */
533 tmpframelength = 256U;
534 }
535 else
536 {
537 /* For free protocol, frame length is set by user */
538 tmpframelength = hsai->FrameInit.FrameLength;
539 }
540
541 /* (freq x 10) to keep Significant digits */
542 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmpframelength);
543 }
544 else
545 {
546 /* NODIV = 0 */
547 uint32_t tmposr;
548 tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
549 /* (freq x 10) to keep Significant digits */
550 tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
551 }
552 hsai->Init.Mckdiv = tmpval / 10U;
553
554 /* Round result to the nearest integer */
555 if ((tmpval % 10U) > 8U)
556 {
557 hsai->Init.Mckdiv += 1U;
558 }
559
560 /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
561 if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
562 {
563 hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
564 }
565 }
566 /* Check the SAI Block master clock divider parameter */
567 assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
568
569 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
570 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
571 {
572 /* Transmit */
573 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
574 }
575 else
576 {
577 /* Receive */
578 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
579 }
580
581 /* SAI Block Configuration -------------------------------------------------*/
582 /* SAI CR1 Configuration */
583 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
584 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
585 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
586 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
587 SAI_xCR1_MCKEN);
588
589 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
590 hsai->Init.DataSize | hsai->Init.FirstBit | \
591 ckstr_bits | syncen_bits | \
592 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
593 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
594 hsai->Init.MckOverSampling | hsai->Init.MckOutput);
595
596 /* SAI CR2 Configuration */
597 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
598 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
599
600 /* SAI Frame Configuration -----------------------------------------*/
601 hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
602 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
603 hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
604 hsai->FrameInit.FSOffset |
605 hsai->FrameInit.FSDefinition |
606 hsai->FrameInit.FSPolarity |
607 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
608
609 /* SAI Block_x SLOT Configuration ------------------------------------------*/
610 /* This register has no meaning in AC 97 and SPDIF audio protocol */
611 hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
612 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
613
614 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
615 (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8);
616
617 /* SAI PDM Configuration ---------------------------------------------------*/
618 if (hsai->Instance == SAI1_Block_A)
619 {
620 /* Disable PDM interface */
621 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
622 if (hsai->Init.PdmInit.Activation == ENABLE)
623 {
624 /* Configure and enable PDM interface */
625 SAI1->PDMCR = (hsai->Init.PdmInit.ClockEnable |
626 ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
627 SAI1->PDMCR |= SAI_PDMCR_PDMEN;
628 }
629 }
630
631 /* Initialize the error code */
632 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
633
634 /* Initialize the SAI state */
635 hsai->State = HAL_SAI_STATE_READY;
636
637 /* Release Lock */
638 __HAL_UNLOCK(hsai);
639
640 return HAL_OK;
641 }
642
643 /**
644 * @brief DeInitialize the SAI peripheral.
645 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
646 * the configuration information for SAI module.
647 * @retval HAL status
648 */
HAL_SAI_DeInit(SAI_HandleTypeDef * hsai)649 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
650 {
651 /* Check the SAI handle allocation */
652 if (hsai == NULL)
653 {
654 return HAL_ERROR;
655 }
656
657 hsai->State = HAL_SAI_STATE_BUSY;
658
659 /* Disabled All interrupt and clear all the flag */
660 hsai->Instance->IMR = 0;
661 hsai->Instance->CLRFR = 0xFFFFFFFFU;
662
663 /* Disable the SAI */
664 if (SAI_Disable(hsai) != HAL_OK)
665 {
666 /* Reset SAI state to ready */
667 hsai->State = HAL_SAI_STATE_READY;
668
669 /* Release Lock */
670 __HAL_UNLOCK(hsai);
671
672 return HAL_ERROR;
673 }
674
675 /* Flush the fifo */
676 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
677
678 /* Disable SAI PDM interface */
679 if (hsai->Instance == SAI1_Block_A)
680 {
681 /* Reset PDM delays */
682 SAI1->PDMDLY = 0U;
683
684 /* Disable PDM interface */
685 SAI1->PDMCR &= ~(SAI_PDMCR_PDMEN);
686 }
687
688 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
689 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
690 if (hsai->MspDeInitCallback == NULL)
691 {
692 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
693 }
694 hsai->MspDeInitCallback(hsai);
695 #else
696 HAL_SAI_MspDeInit(hsai);
697 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
698
699 /* Initialize the error code */
700 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
701
702 /* Initialize the SAI state */
703 hsai->State = HAL_SAI_STATE_RESET;
704
705 /* Release Lock */
706 __HAL_UNLOCK(hsai);
707
708 return HAL_OK;
709 }
710
711 /**
712 * @brief Initialize the SAI MSP.
713 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
714 * the configuration information for SAI module.
715 * @retval None
716 */
HAL_SAI_MspInit(SAI_HandleTypeDef * hsai)717 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
718 {
719 /* Prevent unused argument(s) compilation warning */
720 UNUSED(hsai);
721
722 /* NOTE : This function should not be modified, when the callback is needed,
723 the HAL_SAI_MspInit could be implemented in the user file
724 */
725 }
726
727 /**
728 * @brief DeInitialize the SAI MSP.
729 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
730 * the configuration information for SAI module.
731 * @retval None
732 */
HAL_SAI_MspDeInit(SAI_HandleTypeDef * hsai)733 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
734 {
735 /* Prevent unused argument(s) compilation warning */
736 UNUSED(hsai);
737
738 /* NOTE : This function should not be modified, when the callback is needed,
739 the HAL_SAI_MspDeInit could be implemented in the user file
740 */
741 }
742
743 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
744 /**
745 * @brief Register a user SAI callback
746 * to be used instead of the weak predefined callback.
747 * @param hsai SAI handle.
748 * @param CallbackID ID of the callback to be registered.
749 * This parameter can be one of the following values:
750 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
751 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
752 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
753 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
754 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
755 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
756 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
757 * @param pCallback pointer to the callback function.
758 * @retval HAL status.
759 */
HAL_SAI_RegisterCallback(SAI_HandleTypeDef * hsai,HAL_SAI_CallbackIDTypeDef CallbackID,pSAI_CallbackTypeDef pCallback)760 HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
761 HAL_SAI_CallbackIDTypeDef CallbackID,
762 pSAI_CallbackTypeDef pCallback)
763 {
764 HAL_StatusTypeDef status = HAL_OK;
765
766 if (pCallback == NULL)
767 {
768 /* update the error code */
769 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
770 /* update return status */
771 status = HAL_ERROR;
772 }
773 else
774 {
775 if (HAL_SAI_STATE_READY == hsai->State)
776 {
777 switch (CallbackID)
778 {
779 case HAL_SAI_RX_COMPLETE_CB_ID :
780 hsai->RxCpltCallback = pCallback;
781 break;
782 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
783 hsai->RxHalfCpltCallback = pCallback;
784 break;
785 case HAL_SAI_TX_COMPLETE_CB_ID :
786 hsai->TxCpltCallback = pCallback;
787 break;
788 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
789 hsai->TxHalfCpltCallback = pCallback;
790 break;
791 case HAL_SAI_ERROR_CB_ID :
792 hsai->ErrorCallback = pCallback;
793 break;
794 case HAL_SAI_MSPINIT_CB_ID :
795 hsai->MspInitCallback = pCallback;
796 break;
797 case HAL_SAI_MSPDEINIT_CB_ID :
798 hsai->MspDeInitCallback = pCallback;
799 break;
800 default :
801 /* update the error code */
802 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
803 /* update return status */
804 status = HAL_ERROR;
805 break;
806 }
807 }
808 else if (HAL_SAI_STATE_RESET == hsai->State)
809 {
810 switch (CallbackID)
811 {
812 case HAL_SAI_MSPINIT_CB_ID :
813 hsai->MspInitCallback = pCallback;
814 break;
815 case HAL_SAI_MSPDEINIT_CB_ID :
816 hsai->MspDeInitCallback = pCallback;
817 break;
818 default :
819 /* update the error code */
820 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
821 /* update return status */
822 status = HAL_ERROR;
823 break;
824 }
825 }
826 else
827 {
828 /* update the error code */
829 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
830 /* update return status */
831 status = HAL_ERROR;
832 }
833 }
834 return status;
835 }
836
837 /**
838 * @brief Unregister a user SAI callback.
839 * SAI callback is redirected to the weak predefined callback.
840 * @param hsai SAI handle.
841 * @param CallbackID ID of the callback to be unregistered.
842 * This parameter can be one of the following values:
843 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
844 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
845 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
846 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
847 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
848 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
849 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
850 * @retval HAL status.
851 */
HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef * hsai,HAL_SAI_CallbackIDTypeDef CallbackID)852 HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
853 HAL_SAI_CallbackIDTypeDef CallbackID)
854 {
855 HAL_StatusTypeDef status = HAL_OK;
856
857 if (HAL_SAI_STATE_READY == hsai->State)
858 {
859 switch (CallbackID)
860 {
861 case HAL_SAI_RX_COMPLETE_CB_ID :
862 hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
863 break;
864 case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
865 hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
866 break;
867 case HAL_SAI_TX_COMPLETE_CB_ID :
868 hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
869 break;
870 case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
871 hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
872 break;
873 case HAL_SAI_ERROR_CB_ID :
874 hsai->ErrorCallback = HAL_SAI_ErrorCallback;
875 break;
876 case HAL_SAI_MSPINIT_CB_ID :
877 hsai->MspInitCallback = HAL_SAI_MspInit;
878 break;
879 case HAL_SAI_MSPDEINIT_CB_ID :
880 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
881 break;
882 default :
883 /* update the error code */
884 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
885 /* update return status */
886 status = HAL_ERROR;
887 break;
888 }
889 }
890 else if (HAL_SAI_STATE_RESET == hsai->State)
891 {
892 switch (CallbackID)
893 {
894 case HAL_SAI_MSPINIT_CB_ID :
895 hsai->MspInitCallback = HAL_SAI_MspInit;
896 break;
897 case HAL_SAI_MSPDEINIT_CB_ID :
898 hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
899 break;
900 default :
901 /* update the error code */
902 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
903 /* update return status */
904 status = HAL_ERROR;
905 break;
906 }
907 }
908 else
909 {
910 /* update the error code */
911 hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
912 /* update return status */
913 status = HAL_ERROR;
914 }
915 return status;
916 }
917 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
918
919 /**
920 * @}
921 */
922
923 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
924 * @brief Data transfers functions
925 *
926 @verbatim
927 ==============================================================================
928 ##### IO operation functions #####
929 ==============================================================================
930 [..]
931 This subsection provides a set of functions allowing to manage the SAI data
932 transfers.
933
934 (+) There are two modes of transfer:
935 (++) Blocking mode : The communication is performed in the polling mode.
936 The status of all data processing is returned by the same function
937 after finishing transfer.
938 (++) No-Blocking mode : The communication is performed using Interrupts
939 or DMA. These functions return the status of the transfer startup.
940 The end of the data processing will be indicated through the
941 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
942 using DMA mode.
943
944 (+) Blocking mode functions are :
945 (++) HAL_SAI_Transmit()
946 (++) HAL_SAI_Receive()
947
948 (+) Non Blocking mode functions with Interrupt are :
949 (++) HAL_SAI_Transmit_IT()
950 (++) HAL_SAI_Receive_IT()
951
952 (+) Non Blocking mode functions with DMA are :
953 (++) HAL_SAI_Transmit_DMA()
954 (++) HAL_SAI_Receive_DMA()
955
956 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
957 (++) HAL_SAI_TxCpltCallback()
958 (++) HAL_SAI_RxCpltCallback()
959 (++) HAL_SAI_ErrorCallback()
960
961 @endverbatim
962 * @{
963 */
964
965 /**
966 * @brief Transmit an amount of data in blocking mode.
967 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
968 * the configuration information for SAI module.
969 * @param pData Pointer to data buffer
970 * @param Size Amount of data to be sent
971 * @param Timeout Timeout duration
972 * @retval HAL status
973 */
HAL_SAI_Transmit(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size,uint32_t Timeout)974 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
975 {
976 uint32_t tickstart = HAL_GetTick();
977 uint32_t temp;
978
979 if ((pData == NULL) || (Size == 0U))
980 {
981 return HAL_ERROR;
982 }
983
984 if (hsai->State == HAL_SAI_STATE_READY)
985 {
986 /* Process Locked */
987 __HAL_LOCK(hsai);
988
989 hsai->XferSize = Size;
990 hsai->XferCount = Size;
991 hsai->pBuffPtr = pData;
992 hsai->State = HAL_SAI_STATE_BUSY_TX;
993 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
994
995 /* Check if the SAI is already enabled */
996 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
997 {
998 /* fill the fifo with data before to enabled the SAI */
999 SAI_FillFifo(hsai);
1000 /* Enable SAI peripheral */
1001 __HAL_SAI_ENABLE(hsai);
1002 }
1003
1004 while (hsai->XferCount > 0U)
1005 {
1006 /* Write data if the FIFO is not full */
1007 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
1008 {
1009 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1010 {
1011 hsai->Instance->DR = *hsai->pBuffPtr;
1012 hsai->pBuffPtr++;
1013 }
1014 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1015 {
1016 temp = (uint32_t)(*hsai->pBuffPtr);
1017 hsai->pBuffPtr++;
1018 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1019 hsai->pBuffPtr++;
1020 hsai->Instance->DR = temp;
1021 }
1022 else
1023 {
1024 temp = (uint32_t)(*hsai->pBuffPtr);
1025 hsai->pBuffPtr++;
1026 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
1027 hsai->pBuffPtr++;
1028 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
1029 hsai->pBuffPtr++;
1030 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
1031 hsai->pBuffPtr++;
1032 hsai->Instance->DR = temp;
1033 }
1034 hsai->XferCount--;
1035 }
1036 else
1037 {
1038 /* Check for the Timeout */
1039 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1040 {
1041 /* Update error code */
1042 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1043
1044 /* Clear all the flags */
1045 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1046
1047 /* Disable SAI peripheral */
1048 /* No need to check return value because state update, unlock and error return will be performed later */
1049 (void) SAI_Disable(hsai);
1050
1051 /* Flush the fifo */
1052 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1053
1054 /* Change the SAI state */
1055 hsai->State = HAL_SAI_STATE_READY;
1056
1057 /* Process Unlocked */
1058 __HAL_UNLOCK(hsai);
1059
1060 return HAL_ERROR;
1061 }
1062 }
1063 }
1064
1065 hsai->State = HAL_SAI_STATE_READY;
1066
1067 /* Process Unlocked */
1068 __HAL_UNLOCK(hsai);
1069
1070 return HAL_OK;
1071 }
1072 else
1073 {
1074 return HAL_BUSY;
1075 }
1076 }
1077
1078 /**
1079 * @brief Receive an amount of data in blocking mode.
1080 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1081 * the configuration information for SAI module.
1082 * @param pData Pointer to data buffer
1083 * @param Size Amount of data to be received
1084 * @param Timeout Timeout duration
1085 * @retval HAL status
1086 */
HAL_SAI_Receive(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size,uint32_t Timeout)1087 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
1088 {
1089 uint32_t tickstart = HAL_GetTick();
1090 uint32_t temp;
1091
1092 if ((pData == NULL) || (Size == 0U))
1093 {
1094 return HAL_ERROR;
1095 }
1096
1097 if (hsai->State == HAL_SAI_STATE_READY)
1098 {
1099 /* Process Locked */
1100 __HAL_LOCK(hsai);
1101
1102 hsai->pBuffPtr = pData;
1103 hsai->XferSize = Size;
1104 hsai->XferCount = Size;
1105 hsai->State = HAL_SAI_STATE_BUSY_RX;
1106 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1107
1108 /* Check if the SAI is already enabled */
1109 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1110 {
1111 /* Enable SAI peripheral */
1112 __HAL_SAI_ENABLE(hsai);
1113 }
1114
1115 /* Receive data */
1116 while (hsai->XferCount > 0U)
1117 {
1118 if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
1119 {
1120 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1121 {
1122 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
1123 hsai->pBuffPtr++;
1124 }
1125 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1126 {
1127 temp = hsai->Instance->DR;
1128 *hsai->pBuffPtr = (uint8_t)temp;
1129 hsai->pBuffPtr++;
1130 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1131 hsai->pBuffPtr++;
1132 }
1133 else
1134 {
1135 temp = hsai->Instance->DR;
1136 *hsai->pBuffPtr = (uint8_t)temp;
1137 hsai->pBuffPtr++;
1138 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
1139 hsai->pBuffPtr++;
1140 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
1141 hsai->pBuffPtr++;
1142 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
1143 hsai->pBuffPtr++;
1144 }
1145 hsai->XferCount--;
1146 }
1147 else
1148 {
1149 /* Check for the Timeout */
1150 if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
1151 {
1152 /* Update error code */
1153 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1154
1155 /* Clear all the flags */
1156 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1157
1158 /* Disable SAI peripheral */
1159 /* No need to check return value because state update, unlock and error return will be performed later */
1160 (void) SAI_Disable(hsai);
1161
1162 /* Flush the fifo */
1163 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1164
1165 /* Change the SAI state */
1166 hsai->State = HAL_SAI_STATE_READY;
1167
1168 /* Process Unlocked */
1169 __HAL_UNLOCK(hsai);
1170
1171 return HAL_ERROR;
1172 }
1173 }
1174 }
1175
1176 hsai->State = HAL_SAI_STATE_READY;
1177
1178 /* Process Unlocked */
1179 __HAL_UNLOCK(hsai);
1180
1181 return HAL_OK;
1182 }
1183 else
1184 {
1185 return HAL_BUSY;
1186 }
1187 }
1188
1189 /**
1190 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1191 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1192 * the configuration information for SAI module.
1193 * @param pData Pointer to data buffer
1194 * @param Size Amount of data to be sent
1195 * @retval HAL status
1196 */
HAL_SAI_Transmit_IT(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1197 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1198 {
1199 if ((pData == NULL) || (Size == 0U))
1200 {
1201 return HAL_ERROR;
1202 }
1203
1204 if (hsai->State == HAL_SAI_STATE_READY)
1205 {
1206 /* Process Locked */
1207 __HAL_LOCK(hsai);
1208
1209 hsai->pBuffPtr = pData;
1210 hsai->XferSize = Size;
1211 hsai->XferCount = Size;
1212 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1213 hsai->State = HAL_SAI_STATE_BUSY_TX;
1214
1215 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1216 {
1217 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
1218 }
1219 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1220 {
1221 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
1222 }
1223 else
1224 {
1225 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
1226 }
1227
1228 /* Fill the fifo before starting the communication */
1229 SAI_FillFifo(hsai);
1230
1231 /* Enable FRQ and OVRUDR interrupts */
1232 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1233
1234 /* Check if the SAI is already enabled */
1235 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1236 {
1237 /* Enable SAI peripheral */
1238 __HAL_SAI_ENABLE(hsai);
1239 }
1240 /* Process Unlocked */
1241 __HAL_UNLOCK(hsai);
1242
1243 return HAL_OK;
1244 }
1245 else
1246 {
1247 return HAL_BUSY;
1248 }
1249 }
1250
1251 /**
1252 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1253 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1254 * the configuration information for SAI module.
1255 * @param pData Pointer to data buffer
1256 * @param Size Amount of data to be received
1257 * @retval HAL status
1258 */
HAL_SAI_Receive_IT(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1259 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1260 {
1261 if ((pData == NULL) || (Size == 0U))
1262 {
1263 return HAL_ERROR;
1264 }
1265
1266 if (hsai->State == HAL_SAI_STATE_READY)
1267 {
1268 /* Process Locked */
1269 __HAL_LOCK(hsai);
1270
1271 hsai->pBuffPtr = pData;
1272 hsai->XferSize = Size;
1273 hsai->XferCount = Size;
1274 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1275 hsai->State = HAL_SAI_STATE_BUSY_RX;
1276
1277 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1278 {
1279 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
1280 }
1281 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
1282 {
1283 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
1284 }
1285 else
1286 {
1287 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
1288 }
1289
1290 /* Enable TXE and OVRUDR interrupts */
1291 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1292
1293 /* Check if the SAI is already enabled */
1294 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1295 {
1296 /* Enable SAI peripheral */
1297 __HAL_SAI_ENABLE(hsai);
1298 }
1299
1300 /* Process Unlocked */
1301 __HAL_UNLOCK(hsai);
1302
1303 return HAL_OK;
1304 }
1305 else
1306 {
1307 return HAL_BUSY;
1308 }
1309 }
1310
1311 /**
1312 * @brief Pause the audio stream playing from the Media.
1313 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1314 * the configuration information for SAI module.
1315 * @retval HAL status
1316 */
HAL_SAI_DMAPause(SAI_HandleTypeDef * hsai)1317 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
1318 {
1319 /* Process Locked */
1320 __HAL_LOCK(hsai);
1321
1322 /* Pause the audio file playing by disabling the SAI DMA requests */
1323 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1324
1325 /* Process Unlocked */
1326 __HAL_UNLOCK(hsai);
1327
1328 return HAL_OK;
1329 }
1330
1331 /**
1332 * @brief Resume the audio stream playing from the Media.
1333 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1334 * the configuration information for SAI module.
1335 * @retval HAL status
1336 */
HAL_SAI_DMAResume(SAI_HandleTypeDef * hsai)1337 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
1338 {
1339 /* Process Locked */
1340 __HAL_LOCK(hsai);
1341
1342 /* Enable the SAI DMA requests */
1343 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1344
1345 /* If the SAI peripheral is still not enabled, enable it */
1346 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1347 {
1348 /* Enable SAI peripheral */
1349 __HAL_SAI_ENABLE(hsai);
1350 }
1351
1352 /* Process Unlocked */
1353 __HAL_UNLOCK(hsai);
1354
1355 return HAL_OK;
1356 }
1357
1358 /**
1359 * @brief Stop the audio stream playing from the Media.
1360 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1361 * the configuration information for SAI module.
1362 * @retval HAL status
1363 */
HAL_SAI_DMAStop(SAI_HandleTypeDef * hsai)1364 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
1365 {
1366 HAL_StatusTypeDef status = HAL_OK;
1367
1368 /* Process Locked */
1369 __HAL_LOCK(hsai);
1370
1371 /* Disable the SAI DMA request */
1372 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1373
1374 /* Abort the SAI Tx DMA Stream */
1375 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1376 {
1377 /* No need to check the returned value of HAL_DMA_Abort. */
1378 /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
1379 (void) HAL_DMA_Abort(hsai->hdmatx);
1380 }
1381
1382 /* Abort the SAI Rx DMA Stream */
1383 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1384 {
1385 /* No need to check the returned value of HAL_DMA_Abort. */
1386 /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
1387 (void) HAL_DMA_Abort(hsai->hdmarx);
1388 }
1389
1390 /* Disable SAI peripheral */
1391 if (SAI_Disable(hsai) != HAL_OK)
1392 {
1393 status = HAL_ERROR;
1394 }
1395
1396 /* Flush the fifo */
1397 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1398
1399 /* Set hsai state to ready */
1400 hsai->State = HAL_SAI_STATE_READY;
1401
1402 /* Process Unlocked */
1403 __HAL_UNLOCK(hsai);
1404
1405 return status;
1406 }
1407
1408 /**
1409 * @brief Abort the current transfer and disable the SAI.
1410 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1411 * the configuration information for SAI module.
1412 * @retval HAL status
1413 */
HAL_SAI_Abort(SAI_HandleTypeDef * hsai)1414 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1415 {
1416 HAL_StatusTypeDef status = HAL_OK;
1417
1418 /* Process Locked */
1419 __HAL_LOCK(hsai);
1420
1421 /* Check SAI DMA is enabled or not */
1422 if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1423 {
1424 /* Disable the SAI DMA request */
1425 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1426
1427 /* Abort the SAI Tx DMA Stream */
1428 if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
1429 {
1430 /* No need to check the returned value of HAL_DMA_Abort. */
1431 /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
1432 (void) HAL_DMA_Abort(hsai->hdmatx);
1433 }
1434
1435 /* Abort the SAI Rx DMA Stream */
1436 if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
1437 {
1438 /* No need to check the returned value of HAL_DMA_Abort. */
1439 /* Only HAL_DMA_ERROR_NO_XFER can be returned in case of error and it's not an error for SAI. */
1440 (void) HAL_DMA_Abort(hsai->hdmarx);
1441 }
1442 }
1443
1444 /* Disabled All interrupt and clear all the flag */
1445 hsai->Instance->IMR = 0;
1446 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1447
1448 /* Disable SAI peripheral */
1449 if (SAI_Disable(hsai) != HAL_OK)
1450 {
1451 status = HAL_ERROR;
1452 }
1453
1454 /* Flush the fifo */
1455 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1456
1457 /* Set hsai state to ready */
1458 hsai->State = HAL_SAI_STATE_READY;
1459
1460 /* Process Unlocked */
1461 __HAL_UNLOCK(hsai);
1462
1463 return status;
1464 }
1465
1466 /**
1467 * @brief Transmit an amount of data in non-blocking mode with DMA.
1468 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1469 * the configuration information for SAI module.
1470 * @param pData Pointer to data buffer
1471 * @param Size Amount of data to be sent
1472 * @retval HAL status
1473 */
HAL_SAI_Transmit_DMA(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1474 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1475 {
1476 uint32_t tickstart = HAL_GetTick();
1477
1478 if ((pData == NULL) || (Size == 0U))
1479 {
1480 return HAL_ERROR;
1481 }
1482
1483 if (hsai->State == HAL_SAI_STATE_READY)
1484 {
1485 /* Process Locked */
1486 __HAL_LOCK(hsai);
1487
1488 hsai->pBuffPtr = pData;
1489 hsai->XferSize = Size;
1490 hsai->XferCount = Size;
1491 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1492 hsai->State = HAL_SAI_STATE_BUSY_TX;
1493
1494 /* Set the SAI Tx DMA Half transfer complete callback */
1495 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1496
1497 /* Set the SAI TxDMA transfer complete callback */
1498 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1499
1500 /* Set the DMA error callback */
1501 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1502
1503 /* Set the DMA Tx abort callback */
1504 hsai->hdmatx->XferAbortCallback = NULL;
1505
1506 /* Enable the Tx DMA Stream */
1507 if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1508 {
1509 __HAL_UNLOCK(hsai);
1510 return HAL_ERROR;
1511 }
1512
1513 /* Enable the interrupts for error handling */
1514 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1515
1516 /* Enable SAI Tx DMA Request */
1517 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1518
1519 /* Wait until FIFO is not empty */
1520 while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
1521 {
1522 /* Check for the Timeout */
1523 if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
1524 {
1525 /* Update error code */
1526 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1527
1528 /* Process Unlocked */
1529 __HAL_UNLOCK(hsai);
1530
1531 return HAL_TIMEOUT;
1532 }
1533 }
1534
1535 /* Check if the SAI is already enabled */
1536 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1537 {
1538 /* Enable SAI peripheral */
1539 __HAL_SAI_ENABLE(hsai);
1540 }
1541
1542 /* Process Unlocked */
1543 __HAL_UNLOCK(hsai);
1544
1545 return HAL_OK;
1546 }
1547 else
1548 {
1549 return HAL_BUSY;
1550 }
1551 }
1552
1553 /**
1554 * @brief Receive an amount of data in non-blocking mode with DMA.
1555 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1556 * the configuration information for SAI module.
1557 * @param pData Pointer to data buffer
1558 * @param Size Amount of data to be received
1559 * @retval HAL status
1560 */
HAL_SAI_Receive_DMA(SAI_HandleTypeDef * hsai,uint8_t * pData,uint16_t Size)1561 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1562 {
1563
1564 if ((pData == NULL) || (Size == 0U))
1565 {
1566 return HAL_ERROR;
1567 }
1568
1569 if (hsai->State == HAL_SAI_STATE_READY)
1570 {
1571 /* Process Locked */
1572 __HAL_LOCK(hsai);
1573
1574 hsai->pBuffPtr = pData;
1575 hsai->XferSize = Size;
1576 hsai->XferCount = Size;
1577 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1578 hsai->State = HAL_SAI_STATE_BUSY_RX;
1579
1580 /* Set the SAI Rx DMA Half transfer complete callback */
1581 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1582
1583 /* Set the SAI Rx DMA transfer complete callback */
1584 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1585
1586 /* Set the DMA error callback */
1587 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1588
1589 /* Set the DMA Rx abort callback */
1590 hsai->hdmarx->XferAbortCallback = NULL;
1591
1592 /* Enable the Rx DMA Stream */
1593 if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1594 {
1595 __HAL_UNLOCK(hsai);
1596 return HAL_ERROR;
1597 }
1598
1599 /* Enable the interrupts for error handling */
1600 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1601
1602 /* Enable SAI Rx DMA Request */
1603 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1604
1605 /* Check if the SAI is already enabled */
1606 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
1607 {
1608 /* Enable SAI peripheral */
1609 __HAL_SAI_ENABLE(hsai);
1610 }
1611
1612 /* Process Unlocked */
1613 __HAL_UNLOCK(hsai);
1614
1615 return HAL_OK;
1616 }
1617 else
1618 {
1619 return HAL_BUSY;
1620 }
1621 }
1622
1623 /**
1624 * @brief Enable the Tx mute mode.
1625 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1626 * the configuration information for SAI module.
1627 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1628 * @retval HAL status
1629 */
HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef * hsai,uint16_t val)1630 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1631 {
1632 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1633
1634 if (hsai->State != HAL_SAI_STATE_RESET)
1635 {
1636 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1637 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
1638 return HAL_OK;
1639 }
1640 return HAL_ERROR;
1641 }
1642
1643 /**
1644 * @brief Disable the Tx mute mode.
1645 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1646 * the configuration information for SAI module.
1647 * @retval HAL status
1648 */
HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef * hsai)1649 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1650 {
1651 if (hsai->State != HAL_SAI_STATE_RESET)
1652 {
1653 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1654 return HAL_OK;
1655 }
1656 return HAL_ERROR;
1657 }
1658
1659 /**
1660 * @brief Enable the Rx mute detection.
1661 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1662 * the configuration information for SAI module.
1663 * @param callback function called when the mute is detected.
1664 * @param counter number a data before mute detection max 63.
1665 * @retval HAL status
1666 */
HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef * hsai,SAIcallback callback,uint16_t counter)1667 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1668 {
1669 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1670
1671 if (hsai->State != HAL_SAI_STATE_RESET)
1672 {
1673 /* set the mute counter */
1674 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1675 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1676 hsai->mutecallback = callback;
1677 /* enable the IT interrupt */
1678 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1679 return HAL_OK;
1680 }
1681 return HAL_ERROR;
1682 }
1683
1684 /**
1685 * @brief Disable the Rx mute detection.
1686 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1687 * the configuration information for SAI module.
1688 * @retval HAL status
1689 */
HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef * hsai)1690 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1691 {
1692 if (hsai->State != HAL_SAI_STATE_RESET)
1693 {
1694 /* set the mutecallback to NULL */
1695 hsai->mutecallback = NULL;
1696 /* enable the IT interrupt */
1697 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1698 return HAL_OK;
1699 }
1700 return HAL_ERROR;
1701 }
1702
1703 /**
1704 * @brief Handle SAI interrupt request.
1705 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1706 * the configuration information for SAI module.
1707 * @retval None
1708 */
HAL_SAI_IRQHandler(SAI_HandleTypeDef * hsai)1709 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1710 {
1711 if (hsai->State != HAL_SAI_STATE_RESET)
1712 {
1713 uint32_t itflags = hsai->Instance->SR;
1714 uint32_t itsources = hsai->Instance->IMR;
1715 uint32_t cr1config = hsai->Instance->CR1;
1716 uint32_t tmperror;
1717
1718 /* SAI Fifo request interrupt occurred -----------------------------------*/
1719 if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1720 {
1721 hsai->InterruptServiceRoutine(hsai);
1722 }
1723 /* SAI Overrun error interrupt occurred ----------------------------------*/
1724 else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1725 {
1726 /* Clear the SAI Overrun flag */
1727 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1728 /* Get the SAI error code */
1729 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1730 /* Change the SAI error code */
1731 hsai->ErrorCode |= tmperror;
1732 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1733 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1734 hsai->ErrorCallback(hsai);
1735 #else
1736 HAL_SAI_ErrorCallback(hsai);
1737 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1738 }
1739 /* SAI mutedet interrupt occurred ----------------------------------*/
1740 else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1741 {
1742 /* Clear the SAI mutedet flag */
1743 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1744 /* call the call back function */
1745 if (hsai->mutecallback != NULL)
1746 {
1747 /* inform the user that an RX mute event has been detected */
1748 hsai->mutecallback();
1749 }
1750 }
1751 /* SAI AFSDET interrupt occurred ----------------------------------*/
1752 else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1753 {
1754 /* Clear the SAI AFSDET flag */
1755 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
1756
1757 /* Change the SAI error code */
1758 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1759
1760 /* Check SAI DMA is enabled or not */
1761 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1762 {
1763 /* Abort the SAI DMA Streams */
1764 if (hsai->hdmatx != NULL)
1765 {
1766 /* Set the DMA Tx abort callback */
1767 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1768
1769 /* Abort DMA in IT mode */
1770 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1771 {
1772 /* Update SAI error code */
1773 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1774
1775 /* Call SAI error callback */
1776 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1777 hsai->ErrorCallback(hsai);
1778 #else
1779 HAL_SAI_ErrorCallback(hsai);
1780 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1781 }
1782 }
1783 if (hsai->hdmarx != NULL)
1784 {
1785 /* Set the DMA Rx abort callback */
1786 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1787
1788 /* Abort DMA in IT mode */
1789 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1790 {
1791 /* Update SAI error code */
1792 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1793
1794 /* Call SAI error callback */
1795 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1796 hsai->ErrorCallback(hsai);
1797 #else
1798 HAL_SAI_ErrorCallback(hsai);
1799 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1800 }
1801 }
1802 }
1803 else
1804 {
1805 /* Abort SAI */
1806 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1807 (void) HAL_SAI_Abort(hsai);
1808
1809 /* Set error callback */
1810 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1811 hsai->ErrorCallback(hsai);
1812 #else
1813 HAL_SAI_ErrorCallback(hsai);
1814 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1815 }
1816 }
1817 /* SAI LFSDET interrupt occurred ----------------------------------*/
1818 else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1819 {
1820 /* Clear the SAI LFSDET flag */
1821 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
1822
1823 /* Change the SAI error code */
1824 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1825
1826 /* Check SAI DMA is enabled or not */
1827 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1828 {
1829 /* Abort the SAI DMA Streams */
1830 if (hsai->hdmatx != NULL)
1831 {
1832 /* Set the DMA Tx abort callback */
1833 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1834
1835 /* Abort DMA in IT mode */
1836 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1837 {
1838 /* Update SAI error code */
1839 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1840
1841 /* Call SAI error callback */
1842 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1843 hsai->ErrorCallback(hsai);
1844 #else
1845 HAL_SAI_ErrorCallback(hsai);
1846 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1847 }
1848 }
1849 if (hsai->hdmarx != NULL)
1850 {
1851 /* Set the DMA Rx abort callback */
1852 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1853
1854 /* Abort DMA in IT mode */
1855 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1856 {
1857 /* Update SAI error code */
1858 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1859
1860 /* Call SAI error callback */
1861 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1862 hsai->ErrorCallback(hsai);
1863 #else
1864 HAL_SAI_ErrorCallback(hsai);
1865 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1866 }
1867 }
1868 }
1869 else
1870 {
1871 /* Abort SAI */
1872 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1873 (void) HAL_SAI_Abort(hsai);
1874
1875 /* Set error callback */
1876 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1877 hsai->ErrorCallback(hsai);
1878 #else
1879 HAL_SAI_ErrorCallback(hsai);
1880 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1881 }
1882 }
1883 /* SAI WCKCFG interrupt occurred ----------------------------------*/
1884 else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1885 {
1886 /* Clear the SAI WCKCFG flag */
1887 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
1888
1889 /* Change the SAI error code */
1890 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1891
1892 /* Check SAI DMA is enabled or not */
1893 if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1894 {
1895 /* Abort the SAI DMA Streams */
1896 if (hsai->hdmatx != NULL)
1897 {
1898 /* Set the DMA Tx abort callback */
1899 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1900
1901 /* Abort DMA in IT mode */
1902 if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
1903 {
1904 /* Update SAI error code */
1905 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1906
1907 /* Call SAI error callback */
1908 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1909 hsai->ErrorCallback(hsai);
1910 #else
1911 HAL_SAI_ErrorCallback(hsai);
1912 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1913 }
1914 }
1915 if (hsai->hdmarx != NULL)
1916 {
1917 /* Set the DMA Rx abort callback */
1918 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1919
1920 /* Abort DMA in IT mode */
1921 if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
1922 {
1923 /* Update SAI error code */
1924 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1925
1926 /* Call SAI error callback */
1927 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1928 hsai->ErrorCallback(hsai);
1929 #else
1930 HAL_SAI_ErrorCallback(hsai);
1931 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1932 }
1933 }
1934 }
1935 else
1936 {
1937 /* If WCKCFG occurs, SAI audio block is automatically disabled */
1938 /* Disable all interrupts and clear all flags */
1939 hsai->Instance->IMR = 0U;
1940 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1941 /* Set the SAI state to ready to be able to start again the process */
1942 hsai->State = HAL_SAI_STATE_READY;
1943
1944 /* Initialize XferCount */
1945 hsai->XferCount = 0U;
1946
1947 /* SAI error Callback */
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 */
1953 }
1954 }
1955 /* SAI CNRDY interrupt occurred ----------------------------------*/
1956 else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1957 {
1958 /* Clear the SAI CNRDY flag */
1959 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1960 /* Change the SAI error code */
1961 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1962 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1963 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1964 hsai->ErrorCallback(hsai);
1965 #else
1966 HAL_SAI_ErrorCallback(hsai);
1967 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1968 }
1969 else
1970 {
1971 /* Nothing to do */
1972 }
1973 }
1974 }
1975
1976 /**
1977 * @brief Tx Transfer completed callback.
1978 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1979 * the configuration information for SAI module.
1980 * @retval None
1981 */
HAL_SAI_TxCpltCallback(SAI_HandleTypeDef * hsai)1982 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1983 {
1984 /* Prevent unused argument(s) compilation warning */
1985 UNUSED(hsai);
1986
1987 /* NOTE : This function should not be modified, when the callback is needed,
1988 the HAL_SAI_TxCpltCallback could be implemented in the user file
1989 */
1990 }
1991
1992 /**
1993 * @brief Tx Transfer Half completed callback.
1994 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1995 * the configuration information for SAI module.
1996 * @retval None
1997 */
HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef * hsai)1998 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1999 {
2000 /* Prevent unused argument(s) compilation warning */
2001 UNUSED(hsai);
2002
2003 /* NOTE : This function should not be modified, when the callback is needed,
2004 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2005 */
2006 }
2007
2008 /**
2009 * @brief Rx Transfer completed callback.
2010 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2011 * the configuration information for SAI module.
2012 * @retval None
2013 */
HAL_SAI_RxCpltCallback(SAI_HandleTypeDef * hsai)2014 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
2015 {
2016 /* Prevent unused argument(s) compilation warning */
2017 UNUSED(hsai);
2018
2019 /* NOTE : This function should not be modified, when the callback is needed,
2020 the HAL_SAI_RxCpltCallback could be implemented in the user file
2021 */
2022 }
2023
2024 /**
2025 * @brief Rx Transfer half completed callback.
2026 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2027 * the configuration information for SAI module.
2028 * @retval None
2029 */
HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef * hsai)2030 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
2031 {
2032 /* Prevent unused argument(s) compilation warning */
2033 UNUSED(hsai);
2034
2035 /* NOTE : This function should not be modified, when the callback is needed,
2036 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2037 */
2038 }
2039
2040 /**
2041 * @brief SAI error callback.
2042 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2043 * the configuration information for SAI module.
2044 * @retval None
2045 */
HAL_SAI_ErrorCallback(SAI_HandleTypeDef * hsai)2046 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
2047 {
2048 /* Prevent unused argument(s) compilation warning */
2049 UNUSED(hsai);
2050
2051 /* NOTE : This function should not be modified, when the callback is needed,
2052 the HAL_SAI_ErrorCallback could be implemented in the user file
2053 */
2054 }
2055
2056 /**
2057 * @}
2058 */
2059
2060 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2061 * @brief Peripheral State functions
2062 *
2063 @verbatim
2064 ===============================================================================
2065 ##### Peripheral State and Errors functions #####
2066 ===============================================================================
2067 [..]
2068 This subsection permits to get in run-time the status of the peripheral
2069 and the data flow.
2070
2071 @endverbatim
2072 * @{
2073 */
2074
2075 /**
2076 * @brief Return the SAI handle state.
2077 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2078 * the configuration information for SAI module.
2079 * @retval HAL state
2080 */
HAL_SAI_GetState(SAI_HandleTypeDef * hsai)2081 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
2082 {
2083 return hsai->State;
2084 }
2085
2086 /**
2087 * @brief Return the SAI error code.
2088 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2089 * the configuration information for the specified SAI Block.
2090 * @retval SAI Error Code
2091 */
HAL_SAI_GetError(SAI_HandleTypeDef * hsai)2092 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
2093 {
2094 return hsai->ErrorCode;
2095 }
2096
2097 /**
2098 * @}
2099 */
2100
2101 /**
2102 * @}
2103 */
2104
2105 /** @addtogroup SAI_Private_Functions
2106 * @brief Private functions
2107 * @{
2108 */
2109
2110 /**
2111 * @brief Initialize the SAI I2S protocol according to the specified parameters
2112 * in the SAI_InitTypeDef and create the associated handle.
2113 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2114 * the configuration information for SAI module.
2115 * @param protocol one of the supported protocol.
2116 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2117 * @param nbslot number of slot minimum value is 2 and max is 16.
2118 * the value must be a multiple of 2.
2119 * @retval HAL status
2120 */
SAI_InitI2S(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)2121 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2122 {
2123 HAL_StatusTypeDef status = HAL_OK;
2124
2125 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2126 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2127 /* Compute ClockStrobing according AudioMode */
2128 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2129 {
2130 /* Transmit */
2131 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2132 }
2133 else
2134 {
2135 /* Receive */
2136 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2137 }
2138 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
2139 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2140 hsai->SlotInit.FirstBitOffset = 0;
2141 hsai->SlotInit.SlotNumber = nbslot;
2142
2143 /* in IS2 the number of slot must be even */
2144 if ((nbslot & 0x1U) != 0U)
2145 {
2146 return HAL_ERROR;
2147 }
2148
2149 if (protocol == SAI_I2S_STANDARD)
2150 {
2151 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
2152 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2153 }
2154 else
2155 {
2156 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2157 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2158 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
2159 }
2160
2161 /* Frame definition */
2162 switch (datasize)
2163 {
2164 case SAI_PROTOCOL_DATASIZE_16BIT:
2165 hsai->Init.DataSize = SAI_DATASIZE_16;
2166 hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
2167 hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
2168 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2169 break;
2170 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2171 hsai->Init.DataSize = SAI_DATASIZE_16;
2172 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2173 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2174 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2175 break;
2176 case SAI_PROTOCOL_DATASIZE_24BIT:
2177 hsai->Init.DataSize = SAI_DATASIZE_24;
2178 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2179 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2180 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2181 break;
2182 case SAI_PROTOCOL_DATASIZE_32BIT:
2183 hsai->Init.DataSize = SAI_DATASIZE_32;
2184 hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
2185 hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
2186 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2187 break;
2188 default :
2189 status = HAL_ERROR;
2190 break;
2191 }
2192 if (protocol == SAI_I2S_LSBJUSTIFIED)
2193 {
2194 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
2195 {
2196 hsai->SlotInit.FirstBitOffset = 16;
2197 }
2198 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
2199 {
2200 hsai->SlotInit.FirstBitOffset = 8;
2201 }
2202 }
2203 return status;
2204 }
2205
2206 /**
2207 * @brief Initialize the SAI PCM protocol according to the specified parameters
2208 * in the SAI_InitTypeDef and create the associated handle.
2209 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2210 * the configuration information for SAI module.
2211 * @param protocol one of the supported protocol
2212 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2213 * @param nbslot number of slot minimum value is 1 and the max is 16.
2214 * @retval HAL status
2215 */
SAI_InitPCM(SAI_HandleTypeDef * hsai,uint32_t protocol,uint32_t datasize,uint32_t nbslot)2216 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
2217 {
2218 HAL_StatusTypeDef status = HAL_OK;
2219
2220 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
2221 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
2222 /* Compute ClockStrobing according AudioMode */
2223 if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2224 {
2225 /* Transmit */
2226 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
2227 }
2228 else
2229 {
2230 /* Receive */
2231 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
2232 }
2233 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
2234 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
2235 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
2236 hsai->SlotInit.FirstBitOffset = 0;
2237 hsai->SlotInit.SlotNumber = nbslot;
2238 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
2239
2240 if (protocol == SAI_PCM_SHORT)
2241 {
2242 hsai->FrameInit.ActiveFrameLength = 1;
2243 }
2244 else
2245 {
2246 /* SAI_PCM_LONG */
2247 hsai->FrameInit.ActiveFrameLength = 13;
2248 }
2249
2250 switch (datasize)
2251 {
2252 case SAI_PROTOCOL_DATASIZE_16BIT:
2253 hsai->Init.DataSize = SAI_DATASIZE_16;
2254 hsai->FrameInit.FrameLength = 16U * nbslot;
2255 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
2256 break;
2257 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
2258 hsai->Init.DataSize = SAI_DATASIZE_16;
2259 hsai->FrameInit.FrameLength = 32U * nbslot;
2260 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2261 break;
2262 case SAI_PROTOCOL_DATASIZE_24BIT :
2263 hsai->Init.DataSize = SAI_DATASIZE_24;
2264 hsai->FrameInit.FrameLength = 32U * nbslot;
2265 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2266 break;
2267 case SAI_PROTOCOL_DATASIZE_32BIT:
2268 hsai->Init.DataSize = SAI_DATASIZE_32;
2269 hsai->FrameInit.FrameLength = 32U * nbslot;
2270 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
2271 break;
2272 default :
2273 status = HAL_ERROR;
2274 break;
2275 }
2276
2277 return status;
2278 }
2279
2280 /**
2281 * @brief Fill the fifo.
2282 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2283 * the configuration information for SAI module.
2284 * @retval None
2285 */
SAI_FillFifo(SAI_HandleTypeDef * hsai)2286 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
2287 {
2288 uint32_t temp;
2289
2290 /* fill the fifo with data before to enabled the SAI */
2291 while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
2292 {
2293 if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
2294 {
2295 hsai->Instance->DR = *hsai->pBuffPtr;
2296 hsai->pBuffPtr++;
2297 }
2298 else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
2299 {
2300 temp = (uint32_t)(*hsai->pBuffPtr);
2301 hsai->pBuffPtr++;
2302 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2303 hsai->pBuffPtr++;
2304 hsai->Instance->DR = temp;
2305 }
2306 else
2307 {
2308 temp = (uint32_t)(*hsai->pBuffPtr);
2309 hsai->pBuffPtr++;
2310 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2311 hsai->pBuffPtr++;
2312 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2313 hsai->pBuffPtr++;
2314 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2315 hsai->pBuffPtr++;
2316 hsai->Instance->DR = temp;
2317 }
2318 hsai->XferCount--;
2319 }
2320 }
2321
2322 /**
2323 * @brief Return the interrupt flag to set according the SAI setup.
2324 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2325 * the configuration information for SAI module.
2326 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2327 * @retval the list of the IT flag to enable
2328 */
SAI_InterruptFlag(const SAI_HandleTypeDef * hsai,SAI_ModeTypedef mode)2329 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
2330 {
2331 uint32_t tmpIT = SAI_IT_OVRUDR;
2332
2333 if (mode == SAI_MODE_IT)
2334 {
2335 tmpIT |= SAI_IT_FREQ;
2336 }
2337
2338 if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
2339 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
2340 {
2341 tmpIT |= SAI_IT_CNRDY;
2342 }
2343
2344 if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
2345 {
2346 tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
2347 }
2348 else
2349 {
2350 /* hsai has been configured in master mode */
2351 tmpIT |= SAI_IT_WCKCFG;
2352 }
2353 return tmpIT;
2354 }
2355
2356 /**
2357 * @brief Disable the SAI and wait for the disabling.
2358 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2359 * the configuration information for SAI module.
2360 * @retval None
2361 */
SAI_Disable(SAI_HandleTypeDef * hsai)2362 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
2363 {
2364 uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
2365 HAL_StatusTypeDef status = HAL_OK;
2366
2367 /* Disable the SAI instance */
2368 __HAL_SAI_DISABLE(hsai);
2369
2370 do
2371 {
2372 /* Check for the Timeout */
2373 if (count == 0U)
2374 {
2375 /* Update error code */
2376 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
2377 status = HAL_TIMEOUT;
2378 break;
2379 }
2380 count--;
2381 } while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
2382
2383 return status;
2384 }
2385
2386 /**
2387 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2388 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2389 * the configuration information for SAI module.
2390 * @retval None
2391 */
SAI_Transmit_IT8Bit(SAI_HandleTypeDef * hsai)2392 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
2393 {
2394 if (hsai->XferCount == 0U)
2395 {
2396 /* Handle the end of the transmission */
2397 /* Disable FREQ and OVRUDR interrupts */
2398 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2399 hsai->State = HAL_SAI_STATE_READY;
2400 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2401 hsai->TxCpltCallback(hsai);
2402 #else
2403 HAL_SAI_TxCpltCallback(hsai);
2404 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2405 }
2406 else
2407 {
2408 /* Write data on DR register */
2409 hsai->Instance->DR = *hsai->pBuffPtr;
2410 hsai->pBuffPtr++;
2411 hsai->XferCount--;
2412 }
2413 }
2414
2415 /**
2416 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2417 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2418 * the configuration information for SAI module.
2419 * @retval None
2420 */
SAI_Transmit_IT16Bit(SAI_HandleTypeDef * hsai)2421 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
2422 {
2423 if (hsai->XferCount == 0U)
2424 {
2425 /* Handle the end of the transmission */
2426 /* Disable FREQ and OVRUDR interrupts */
2427 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2428 hsai->State = HAL_SAI_STATE_READY;
2429 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2430 hsai->TxCpltCallback(hsai);
2431 #else
2432 HAL_SAI_TxCpltCallback(hsai);
2433 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2434 }
2435 else
2436 {
2437 /* Write data on DR register */
2438 uint32_t temp;
2439 temp = (uint32_t)(*hsai->pBuffPtr);
2440 hsai->pBuffPtr++;
2441 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2442 hsai->pBuffPtr++;
2443 hsai->Instance->DR = temp;
2444 hsai->XferCount--;
2445 }
2446 }
2447
2448 /**
2449 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2450 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2451 * the configuration information for SAI module.
2452 * @retval None
2453 */
SAI_Transmit_IT32Bit(SAI_HandleTypeDef * hsai)2454 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
2455 {
2456 if (hsai->XferCount == 0U)
2457 {
2458 /* Handle the end of the transmission */
2459 /* Disable FREQ and OVRUDR interrupts */
2460 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2461 hsai->State = HAL_SAI_STATE_READY;
2462 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2463 hsai->TxCpltCallback(hsai);
2464 #else
2465 HAL_SAI_TxCpltCallback(hsai);
2466 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2467 }
2468 else
2469 {
2470 /* Write data on DR register */
2471 uint32_t temp;
2472 temp = (uint32_t)(*hsai->pBuffPtr);
2473 hsai->pBuffPtr++;
2474 temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
2475 hsai->pBuffPtr++;
2476 temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
2477 hsai->pBuffPtr++;
2478 temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
2479 hsai->pBuffPtr++;
2480 hsai->Instance->DR = temp;
2481 hsai->XferCount--;
2482 }
2483 }
2484
2485 /**
2486 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2487 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2488 * the configuration information for SAI module.
2489 * @retval None
2490 */
SAI_Receive_IT8Bit(SAI_HandleTypeDef * hsai)2491 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
2492 {
2493 /* Receive data */
2494 *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
2495 hsai->pBuffPtr++;
2496 hsai->XferCount--;
2497
2498 /* Check end of the transfer */
2499 if (hsai->XferCount == 0U)
2500 {
2501 /* Disable TXE and OVRUDR interrupts */
2502 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2503
2504 /* Clear the SAI Overrun flag */
2505 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2506
2507 hsai->State = HAL_SAI_STATE_READY;
2508 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2509 hsai->RxCpltCallback(hsai);
2510 #else
2511 HAL_SAI_RxCpltCallback(hsai);
2512 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2513 }
2514 }
2515
2516 /**
2517 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2518 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2519 * the configuration information for SAI module.
2520 * @retval None
2521 */
SAI_Receive_IT16Bit(SAI_HandleTypeDef * hsai)2522 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2523 {
2524 uint32_t temp;
2525
2526 /* Receive data */
2527 temp = hsai->Instance->DR;
2528 *hsai->pBuffPtr = (uint8_t)temp;
2529 hsai->pBuffPtr++;
2530 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2531 hsai->pBuffPtr++;
2532 hsai->XferCount--;
2533
2534 /* Check end of the transfer */
2535 if (hsai->XferCount == 0U)
2536 {
2537 /* Disable TXE and OVRUDR interrupts */
2538 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2539
2540 /* Clear the SAI Overrun flag */
2541 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2542
2543 hsai->State = HAL_SAI_STATE_READY;
2544 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2545 hsai->RxCpltCallback(hsai);
2546 #else
2547 HAL_SAI_RxCpltCallback(hsai);
2548 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2549 }
2550 }
2551
2552 /**
2553 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2554 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2555 * the configuration information for SAI module.
2556 * @retval None
2557 */
SAI_Receive_IT32Bit(SAI_HandleTypeDef * hsai)2558 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2559 {
2560 uint32_t temp;
2561
2562 /* Receive data */
2563 temp = hsai->Instance->DR;
2564 *hsai->pBuffPtr = (uint8_t)temp;
2565 hsai->pBuffPtr++;
2566 *hsai->pBuffPtr = (uint8_t)(temp >> 8);
2567 hsai->pBuffPtr++;
2568 *hsai->pBuffPtr = (uint8_t)(temp >> 16);
2569 hsai->pBuffPtr++;
2570 *hsai->pBuffPtr = (uint8_t)(temp >> 24);
2571 hsai->pBuffPtr++;
2572 hsai->XferCount--;
2573
2574 /* Check end of the transfer */
2575 if (hsai->XferCount == 0U)
2576 {
2577 /* Disable TXE and OVRUDR interrupts */
2578 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2579
2580 /* Clear the SAI Overrun flag */
2581 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2582
2583 hsai->State = HAL_SAI_STATE_READY;
2584 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2585 hsai->RxCpltCallback(hsai);
2586 #else
2587 HAL_SAI_RxCpltCallback(hsai);
2588 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2589 }
2590 }
2591
2592 /**
2593 * @brief DMA SAI transmit process complete callback.
2594 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2595 * the configuration information for the specified DMA module.
2596 * @retval None
2597 */
SAI_DMATxCplt(DMA_HandleTypeDef * hdma)2598 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2599 {
2600 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2601
2602 if (hdma->Init.Mode != DMA_CIRCULAR)
2603 {
2604 hsai->XferCount = 0;
2605
2606 /* Disable SAI Tx DMA Request */
2607 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2608
2609 /* Stop the interrupts error handling */
2610 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2611
2612 hsai->State = HAL_SAI_STATE_READY;
2613 }
2614 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2615 hsai->TxCpltCallback(hsai);
2616 #else
2617 HAL_SAI_TxCpltCallback(hsai);
2618 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2619 }
2620
2621 /**
2622 * @brief DMA SAI transmit process half complete callback.
2623 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2624 * the configuration information for the specified DMA module.
2625 * @retval None
2626 */
SAI_DMATxHalfCplt(DMA_HandleTypeDef * hdma)2627 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2628 {
2629 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2630
2631 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2632 hsai->TxHalfCpltCallback(hsai);
2633 #else
2634 HAL_SAI_TxHalfCpltCallback(hsai);
2635 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2636 }
2637
2638 /**
2639 * @brief DMA SAI receive process complete callback.
2640 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2641 * the configuration information for the specified DMA module.
2642 * @retval None
2643 */
SAI_DMARxCplt(DMA_HandleTypeDef * hdma)2644 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2645 {
2646 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2647
2648 if (hdma->Init.Mode != DMA_CIRCULAR)
2649 {
2650 /* Disable Rx DMA Request */
2651 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2652 hsai->XferCount = 0;
2653
2654 /* Stop the interrupts error handling */
2655 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2656
2657 hsai->State = HAL_SAI_STATE_READY;
2658 }
2659 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2660 hsai->RxCpltCallback(hsai);
2661 #else
2662 HAL_SAI_RxCpltCallback(hsai);
2663 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2664 }
2665
2666 /**
2667 * @brief DMA SAI receive process half complete callback
2668 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2669 * the configuration information for the specified DMA module.
2670 * @retval None
2671 */
SAI_DMARxHalfCplt(DMA_HandleTypeDef * hdma)2672 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2673 {
2674 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2675
2676 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2677 hsai->RxHalfCpltCallback(hsai);
2678 #else
2679 HAL_SAI_RxHalfCpltCallback(hsai);
2680 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2681 }
2682
2683 /**
2684 * @brief DMA SAI communication error callback.
2685 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2686 * the configuration information for the specified DMA module.
2687 * @retval None
2688 */
SAI_DMAError(DMA_HandleTypeDef * hdma)2689 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2690 {
2691 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2692
2693 /* Set SAI error code */
2694 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2695
2696 /* Disable the SAI DMA request */
2697 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2698
2699 /* Disable SAI peripheral */
2700 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2701 (void) SAI_Disable(hsai);
2702
2703 /* Set the SAI state ready to be able to start again the process */
2704 hsai->State = HAL_SAI_STATE_READY;
2705
2706 /* Initialize XferCount */
2707 hsai->XferCount = 0U;
2708
2709 /* SAI error Callback */
2710 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2711 hsai->ErrorCallback(hsai);
2712 #else
2713 HAL_SAI_ErrorCallback(hsai);
2714 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2715 }
2716
2717 /**
2718 * @brief DMA SAI Abort callback.
2719 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2720 * the configuration information for the specified DMA module.
2721 * @retval None
2722 */
SAI_DMAAbort(DMA_HandleTypeDef * hdma)2723 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2724 {
2725 SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
2726
2727 /* Disable DMA request */
2728 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2729
2730 /* Disable all interrupts and clear all flags */
2731 hsai->Instance->IMR = 0U;
2732 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2733
2734 if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2735 {
2736 /* Disable SAI peripheral */
2737 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2738 (void) SAI_Disable(hsai);
2739
2740 /* Flush the fifo */
2741 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2742 }
2743 /* Set the SAI state to ready to be able to start again the process */
2744 hsai->State = HAL_SAI_STATE_READY;
2745
2746 /* Initialize XferCount */
2747 hsai->XferCount = 0U;
2748
2749 /* SAI error Callback */
2750 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2751 hsai->ErrorCallback(hsai);
2752 #else
2753 HAL_SAI_ErrorCallback(hsai);
2754 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
2755 }
2756
2757 /**
2758 * @}
2759 */
2760
2761 #endif /* HAL_SAI_MODULE_ENABLED */
2762 /**
2763 * @}
2764 */
2765
2766 /**
2767 * @}
2768 */
2769
2770