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