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