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