source: S-port/trunk/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c

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