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