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