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