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