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