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