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