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