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