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