2 ******************************************************************************
3 * @file stm32h7xx_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
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
19 The SAI HAL driver can be used as follows:
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.
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
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().
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.
51 (@) Make sure that either:
52 (+@) PLLSAI1CLK output is configured or
53 (+@) PLLSAI2CLK output is configured or
54 (+@) PLLSAI3CLK output is configured or
55 (+@) PLLSAI4ACLK output is configured or
56 (+@) PLLSAI4BCLK output is configured or
57 (+@) External clock source is configured after setting correctly
58 the define constant EXTERNAL_CLOCK_VALUE in the stm32h7xx_hal_conf.h file.
61 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
62 for the external slaves even if there is no data in the FIFO, However FS signal
63 generation is conditioned by the presence of data in the FIFO.
66 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
67 and FS signal for the external slaves.
70 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
71 (+@) First bit Offset <= (SLOT size - Data size)
72 (+@) Data size <= SLOT size
73 (+@) Number of SLOT x SLOT size = Frame length
74 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
77 (@) PDM interface can be activated through HAL_SAI_Init function.
78 Please note that PDM interface is only available for SAI1 or SAI4 sub-block A.
79 PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
82 Three operation modes are available within this driver :
84 *** Polling mode IO operation ***
85 =================================
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()
90 *** Interrupt mode IO operation ***
91 ===================================
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()
102 *** DMA mode IO operation ***
103 =============================
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()
117 *** SAI HAL driver additional function list ***
118 ===============================================
120 Below the list the others API available SAI HAL driver :
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
129 *** SAI HAL driver macros list ***
130 ==================================
132 Below the list of most used macros in SAI HAL driver :
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
140 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
142 *** Callback registration ***
143 =============================
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.
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.
159 This function takes as parameters the HAL peripheral handle, the callback ID
160 and a pointer to the user callback function.
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,
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.
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).
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.
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.
202 ******************************************************************************
205 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
206 * All rights reserved.</center></h2>
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
213 ******************************************************************************
216 /* Includes ------------------------------------------------------------------*/
217 #include "stm32h7xx_hal.h"
219 /** @addtogroup STM32H7xx_HAL_Driver
223 /** @defgroup SAI SAI
224 * @brief SAI HAL module driver
228 #ifdef HAL_SAI_MODULE_ENABLED
230 /* Private typedef -----------------------------------------------------------*/
231 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
243 /* Private define ------------------------------------------------------------*/
244 /** @defgroup SAI_Private_Constants SAI Private Constants
247 #define SAI_DEFAULT_TIMEOUT 4U
248 #define SAI_LONG_TIMEOUT 1000U
253 /* Private macro -------------------------------------------------------------*/
254 /* Private variables ---------------------------------------------------------*/
255 /* Private function prototypes -----------------------------------------------*/
256 /** @defgroup SAI_Private_Functions SAI Private Functions
259 static void SAI_FillFifo(SAI_HandleTypeDef
*hsai
);
260 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef
*hsai
, SAI_ModeTypedef mode
);
261 static HAL_StatusTypeDef
SAI_InitI2S(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
);
262 static HAL_StatusTypeDef
SAI_InitPCM(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
);
264 static HAL_StatusTypeDef
SAI_Disable(SAI_HandleTypeDef
*hsai
);
265 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef
*hsai
);
266 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef
*hsai
);
267 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef
*hsai
);
268 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef
*hsai
);
269 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef
*hsai
);
270 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef
*hsai
);
272 static void SAI_DMATxCplt(DMA_HandleTypeDef
*hdma
);
273 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef
*hdma
);
274 static void SAI_DMARxCplt(DMA_HandleTypeDef
*hdma
);
275 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef
*hdma
);
276 static void SAI_DMAError(DMA_HandleTypeDef
*hdma
);
277 static void SAI_DMAAbort(DMA_HandleTypeDef
*hdma
);
282 /* Exported functions ---------------------------------------------------------*/
283 /** @defgroup SAI_Exported_Functions SAI Exported Functions
287 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
288 * @brief Initialization and Configuration functions
291 ===============================================================================
292 ##### Initialization and de-initialization functions #####
293 ===============================================================================
294 [..] This subsection provides a set of functions allowing to initialize and
295 de-initialize the SAIx peripheral:
297 (+) User must implement HAL_SAI_MspInit() function in which he configures
298 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
300 (+) Call the function HAL_SAI_Init() to configure the selected device with
301 the selected configuration:
302 (++) Mode (Master/slave TX/RX)
312 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
313 of the selected SAI peripheral.
320 * @brief Initialize the structure FrameInit, SlotInit and the low part of
321 * Init according to the specified parameters and call the function
322 * HAL_SAI_Init to initialize the SAI block.
323 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
324 * the configuration information for SAI module.
325 * @param protocol one of the supported protocol @ref SAI_Protocol
326 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
327 * the configuration information for SAI module.
328 * @param nbslot Number of slot.
331 HAL_StatusTypeDef
HAL_SAI_InitProtocol(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
333 HAL_StatusTypeDef status
;
335 /* Check the parameters */
336 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol
));
337 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize
));
341 case SAI_I2S_STANDARD
:
342 case SAI_I2S_MSBJUSTIFIED
:
343 case SAI_I2S_LSBJUSTIFIED
:
344 status
= SAI_InitI2S(hsai
, protocol
, datasize
, nbslot
);
348 status
= SAI_InitPCM(hsai
, protocol
, datasize
, nbslot
);
355 if (status
== HAL_OK
)
357 status
= HAL_SAI_Init(hsai
);
364 * @brief Initialize the SAI according to the specified parameters.
365 * in the SAI_InitTypeDef structure and initialize the associated handle.
366 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
367 * the configuration information for SAI module.
370 HAL_StatusTypeDef
HAL_SAI_Init(SAI_HandleTypeDef
*hsai
)
372 uint32_t tmpregisterGCR
;
374 uint32_t syncen_bits
;
375 SAI_TypeDef
*SaiBaseAddress
;
377 /* Check the SAI handle allocation */
383 /* check the instance */
384 assert_param(IS_SAI_ALL_INSTANCE(hsai
->Instance
));
386 /* Check the SAI Block parameters */
387 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai
->Init
.AudioFrequency
));
388 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai
->Init
.Protocol
));
389 assert_param(IS_SAI_BLOCK_MODE(hsai
->Init
.AudioMode
));
390 assert_param(IS_SAI_BLOCK_DATASIZE(hsai
->Init
.DataSize
));
391 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai
->Init
.FirstBit
));
392 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai
->Init
.ClockStrobing
));
393 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai
->Init
.Synchro
));
394 #if defined(SAI_VER_V2_X)
395 /* SAI Peripheral version depends on STM32H7 device revision ID */
396 if (HAL_GetREVID() >= REV_ID_B
) /* STM32H7xx Rev.B and above */
398 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai
->Init
.MckOutput
));
400 #else /* SAI_VER_V2_1 */
401 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai
->Init
.MckOutput
));
402 #endif /* SAI_VER_V2_X */
403 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai
->Init
.OutputDrive
));
404 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai
->Init
.NoDivider
));
405 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai
->Init
.FIFOThreshold
));
406 assert_param(IS_SAI_MONO_STEREO_MODE(hsai
->Init
.MonoStereoMode
));
407 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai
->Init
.CompandingMode
));
408 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai
->Init
.TriState
));
409 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai
->Init
.SynchroExt
));
410 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai
->Init
.MckOverSampling
));
412 /* Check the SAI Block Frame parameters */
413 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai
->FrameInit
.FrameLength
));
414 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai
->FrameInit
.ActiveFrameLength
));
415 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai
->FrameInit
.FSDefinition
));
416 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai
->FrameInit
.FSPolarity
));
417 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai
->FrameInit
.FSOffset
));
419 /* Check the SAI Block Slot parameters */
420 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai
->SlotInit
.FirstBitOffset
));
421 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai
->SlotInit
.SlotSize
));
422 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai
->SlotInit
.SlotNumber
));
423 assert_param(IS_SAI_SLOT_ACTIVE(hsai
->SlotInit
.SlotActive
));
425 /* Check the SAI PDM parameters */
426 assert_param(IS_FUNCTIONAL_STATE(hsai
->Init
.PdmInit
.Activation
));
427 if (hsai
->Init
.PdmInit
.Activation
== ENABLE
)
429 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai
->Init
.PdmInit
.MicPairsNbr
));
430 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai
->Init
.PdmInit
.ClockEnable
));
431 /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
433 if (((hsai
->Instance
!= SAI1_Block_A
) && (hsai
->Instance
!= SAI4_Block_A
)) ||
434 (hsai
->Init
.AudioMode
!= SAI_MODEMASTER_RX
) ||
435 (hsai
->Init
.Protocol
!= SAI_FREE_PROTOCOL
))
440 if ((hsai
->Instance
!= SAI1_Block_A
) ||
441 (hsai
->Init
.AudioMode
!= SAI_MODEMASTER_RX
) ||
442 (hsai
->Init
.Protocol
!= SAI_FREE_PROTOCOL
))
449 /* Get the SAI base address according to the SAI handle */
450 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI1_Block_B
))
452 SaiBaseAddress
= SAI1
;
455 else if ((hsai
->Instance
== SAI2_Block_A
) || (hsai
->Instance
== SAI2_Block_B
))
457 SaiBaseAddress
= SAI2
;
461 else if ((hsai
->Instance
== SAI3_Block_A
) || (hsai
->Instance
== SAI3_Block_B
))
463 SaiBaseAddress
= SAI3
;
467 else if ((hsai
->Instance
== SAI4_Block_A
) || (hsai
->Instance
== SAI4_Block_B
))
469 SaiBaseAddress
= SAI4
;
477 if (hsai
->State
== HAL_SAI_STATE_RESET
)
479 /* Allocate lock resource and initialize it */
480 hsai
->Lock
= HAL_UNLOCKED
;
482 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
483 /* Reset callback pointers to the weak predefined callbacks */
484 hsai
->RxCpltCallback
= HAL_SAI_RxCpltCallback
;
485 hsai
->RxHalfCpltCallback
= HAL_SAI_RxHalfCpltCallback
;
486 hsai
->TxCpltCallback
= HAL_SAI_TxCpltCallback
;
487 hsai
->TxHalfCpltCallback
= HAL_SAI_TxHalfCpltCallback
;
488 hsai
->ErrorCallback
= HAL_SAI_ErrorCallback
;
490 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
491 if (hsai
->MspInitCallback
== NULL
)
493 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
495 hsai
->MspInitCallback(hsai
);
497 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
498 HAL_SAI_MspInit(hsai
);
502 /* Disable the selected SAI peripheral */
503 if(SAI_Disable(hsai
) != HAL_OK
)
508 hsai
->State
= HAL_SAI_STATE_BUSY
;
510 /* SAI Block Synchro Configuration -----------------------------------------*/
511 /* This setting must be done with both audio block (A & B) disabled */
512 switch (hsai
->Init
.SynchroExt
)
514 case SAI_SYNCEXT_DISABLE
:
517 case SAI_SYNCEXT_OUTBLOCKA_ENABLE
:
518 tmpregisterGCR
= SAI_GCR_SYNCOUT_0
;
520 case SAI_SYNCEXT_OUTBLOCKB_ENABLE
:
521 tmpregisterGCR
= SAI_GCR_SYNCOUT_1
;
528 switch (hsai
->Init
.Synchro
)
530 case SAI_ASYNCHRONOUS
:
533 case SAI_SYNCHRONOUS
:
534 syncen_bits
= SAI_xCR1_SYNCEN_0
;
536 case SAI_SYNCHRONOUS_EXT_SAI1
:
537 syncen_bits
= SAI_xCR1_SYNCEN_1
;
540 case SAI_SYNCHRONOUS_EXT_SAI2
:
541 syncen_bits
= SAI_xCR1_SYNCEN_1
;
542 tmpregisterGCR
|= SAI_GCR_SYNCIN_0
;
546 case SAI_SYNCHRONOUS_EXT_SAI3
:
547 syncen_bits
= SAI_xCR1_SYNCEN_1
;
548 tmpregisterGCR
|= SAI_GCR_SYNCIN_1
;
552 case SAI_SYNCHRONOUS_EXT_SAI4
:
553 syncen_bits
= SAI_xCR1_SYNCEN_1
;
554 tmpregisterGCR
|= (SAI_GCR_SYNCIN_1
| SAI_GCR_SYNCIN_0
);
562 /* Set the SAI Block Synchro Configuration */
563 SaiBaseAddress
->GCR
= tmpregisterGCR
;
565 if (hsai
->Init
.AudioFrequency
!= SAI_AUDIO_FREQUENCY_MCKDIV
)
570 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
571 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI1_Block_B
))
573 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1
);
577 #if defined(RCC_PERIPHCLK_SAI2)
578 if ((hsai
->Instance
== SAI2_Block_A
) || (hsai
->Instance
== SAI2_Block_B
))
580 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2
);
583 if (hsai
->Instance
== SAI2_Block_A
)
585 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A
);
587 if (hsai
->Instance
== SAI2_Block_B
)
589 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B
);
591 #endif /* RCC_PERIPHCLK_SAI2 */
595 if ((hsai
->Instance
== SAI3_Block_A
) || (hsai
->Instance
== SAI3_Block_B
))
597 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3
);
601 if (hsai
->Instance
== SAI4_Block_A
)
603 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A
);
605 if (hsai
->Instance
== SAI4_Block_B
)
607 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B
);
611 /* Configure Master Clock Divider using the following formula :
613 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
615 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
616 if (hsai
->Init
.NoDivider
== SAI_MASTERDIVIDER_DISABLE
)
619 uint32_t tmpframelength
;
621 if (hsai
->Init
.Protocol
== SAI_SPDIF_PROTOCOL
)
623 /* For SPDIF protocol, frame length is set by hardware to 64 */
624 tmpframelength
= 64U;
626 else if (hsai
->Init
.Protocol
== SAI_AC97_PROTOCOL
)
628 /* For AC97 protocol, frame length is set by hardware to 256 */
629 tmpframelength
= 256U;
633 /* For free protocol, frame length is set by user */
634 tmpframelength
= hsai
->FrameInit
.FrameLength
;
637 /* (freq x 10) to keep Significant digits */
638 tmpval
= (freq
* 10U) / (hsai
->Init
.AudioFrequency
* tmpframelength
);
644 tmposr
= (hsai
->Init
.MckOverSampling
== SAI_MCK_OVERSAMPLING_ENABLE
) ? 2U : 1U;
645 /* (freq x 10) to keep Significant digits */
646 tmpval
= (freq
* 10U) / (hsai
->Init
.AudioFrequency
* tmposr
* 256U);
648 hsai
->Init
.Mckdiv
= tmpval
/ 10U;
650 /* Round result to the nearest integer */
651 if ((tmpval
% 10U) > 8U)
653 hsai
->Init
.Mckdiv
+= 1U;
656 /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
657 if (hsai
->Init
.Protocol
== SAI_SPDIF_PROTOCOL
)
659 hsai
->Init
.Mckdiv
= hsai
->Init
.Mckdiv
>> 1;
663 /* Check the SAI Block master clock divider parameter */
664 assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai
->Init
.Mckdiv
));
666 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
667 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
670 ckstr_bits
= (hsai
->Init
.ClockStrobing
== SAI_CLOCKSTROBING_RISINGEDGE
) ? 0U : SAI_xCR1_CKSTR
;
675 ckstr_bits
= (hsai
->Init
.ClockStrobing
== SAI_CLOCKSTROBING_RISINGEDGE
) ? SAI_xCR1_CKSTR
: 0U;
678 /* SAI Block Configuration -------------------------------------------------*/
679 /* SAI CR1 Configuration */
680 #if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
682 if (HAL_GetREVID() >= REV_ID_B
) /* STM32H7xx Rev.B and above */
684 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
685 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
686 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
687 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
| \
690 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
691 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
692 ckstr_bits
| syncen_bits
| \
693 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
694 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
695 hsai
->Init
.MckOverSampling
| hsai
->Init
.MckOutput
);
697 else /* STM32H7xx Rev.Y */
699 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
700 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
701 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
702 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
);
704 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
705 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
706 ckstr_bits
| syncen_bits
| \
707 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
708 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
709 hsai
->Init
.MckOverSampling
);
711 #else /* SAI_VER_V2_1*/
712 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
713 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
714 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
715 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
| \
718 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
719 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
720 ckstr_bits
| syncen_bits
| \
721 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
722 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
723 hsai
->Init
.MckOverSampling
| hsai
->Init
.MckOutput
);
724 #endif /* SAI_VER_V2_X */
726 /* SAI CR2 Configuration */
727 hsai
->Instance
->CR2
&= ~(SAI_xCR2_FTH
| SAI_xCR2_FFLUSH
| SAI_xCR2_COMP
| SAI_xCR2_CPL
);
728 hsai
->Instance
->CR2
|= (hsai
->Init
.FIFOThreshold
| hsai
->Init
.CompandingMode
| hsai
->Init
.TriState
);
730 /* SAI Frame Configuration -----------------------------------------*/
731 hsai
->Instance
->FRCR
&= (~(SAI_xFRCR_FRL
| SAI_xFRCR_FSALL
| SAI_xFRCR_FSDEF
| \
732 SAI_xFRCR_FSPOL
| SAI_xFRCR_FSOFF
));
733 hsai
->Instance
->FRCR
|= ((hsai
->FrameInit
.FrameLength
- 1U) |
734 hsai
->FrameInit
.FSOffset
|
735 hsai
->FrameInit
.FSDefinition
|
736 hsai
->FrameInit
.FSPolarity
|
737 ((hsai
->FrameInit
.ActiveFrameLength
- 1U) << 8));
739 /* SAI Block_x SLOT Configuration ------------------------------------------*/
740 /* This register has no meaning in AC 97 and SPDIF audio protocol */
741 hsai
->Instance
->SLOTR
&= (~(SAI_xSLOTR_FBOFF
| SAI_xSLOTR_SLOTSZ
| \
742 SAI_xSLOTR_NBSLOT
| SAI_xSLOTR_SLOTEN
));
744 hsai
->Instance
->SLOTR
|= hsai
->SlotInit
.FirstBitOffset
| hsai
->SlotInit
.SlotSize
| \
745 (hsai
->SlotInit
.SlotActive
<< 16) | ((hsai
->SlotInit
.SlotNumber
- 1U) << 8);
747 /* SAI PDM Configuration ---------------------------------------------------*/
749 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI4_Block_A
))
751 if (hsai
->Instance
== SAI1_Block_A
)
754 /* Disable PDM interface */
755 SaiBaseAddress
->PDMCR
&= ~(SAI_PDMCR_PDMEN
);
756 if (hsai
->Init
.PdmInit
.Activation
== ENABLE
)
758 /* Configure and enable PDM interface */
759 SaiBaseAddress
->PDMCR
= (hsai
->Init
.PdmInit
.ClockEnable
|
760 ((hsai
->Init
.PdmInit
.MicPairsNbr
- 1U) << SAI_PDMCR_MICNBR_Pos
));
761 SaiBaseAddress
->PDMCR
|= SAI_PDMCR_PDMEN
;
765 /* Initialize the error code */
766 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
768 /* Initialize the SAI state */
769 hsai
->State
= HAL_SAI_STATE_READY
;
778 * @brief DeInitialize the SAI peripheral.
779 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
780 * the configuration information for SAI module.
783 HAL_StatusTypeDef
HAL_SAI_DeInit(SAI_HandleTypeDef
*hsai
)
785 SAI_TypeDef
*SaiBaseAddress
;
787 /* Check the SAI handle allocation */
793 hsai
->State
= HAL_SAI_STATE_BUSY
;
795 /* Disabled All interrupt and clear all the flag */
796 hsai
->Instance
->IMR
= 0;
797 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
799 /* Disable the SAI */
800 if (SAI_Disable(hsai
) != HAL_OK
)
802 /* Reset SAI state to ready */
803 hsai
->State
= HAL_SAI_STATE_READY
;
812 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
814 /* Disable SAI PDM interface */
816 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI4_Block_A
))
818 if (hsai
->Instance
== SAI1_Block_A
)
821 /* Get the SAI base address according to the SAI handle */
823 SaiBaseAddress
= (hsai
->Instance
== SAI1_Block_A
) ? SAI1
: SAI4
;
825 SaiBaseAddress
= SAI1
;
828 /* Reset PDM delays */
829 SaiBaseAddress
->PDMDLY
= 0U;
831 /* Disable PDM interface */
832 SaiBaseAddress
->PDMCR
&= ~(SAI_PDMCR_PDMEN
);
835 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
836 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
837 if (hsai
->MspDeInitCallback
== NULL
)
839 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
841 hsai
->MspDeInitCallback(hsai
);
843 HAL_SAI_MspDeInit(hsai
);
846 /* Initialize the error code */
847 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
849 /* Initialize the SAI state */
850 hsai
->State
= HAL_SAI_STATE_RESET
;
859 * @brief Initialize the SAI MSP.
860 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
861 * the configuration information for SAI module.
864 __weak
void HAL_SAI_MspInit(SAI_HandleTypeDef
*hsai
)
866 /* Prevent unused argument(s) compilation warning */
869 /* NOTE : This function should not be modified, when the callback is needed,
870 the HAL_SAI_MspInit could be implemented in the user file
875 * @brief DeInitialize the SAI MSP.
876 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
877 * the configuration information for SAI module.
880 __weak
void HAL_SAI_MspDeInit(SAI_HandleTypeDef
*hsai
)
882 /* Prevent unused argument(s) compilation warning */
885 /* NOTE : This function should not be modified, when the callback is needed,
886 the HAL_SAI_MspDeInit could be implemented in the user file
890 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
892 * @brief Register a user SAI callback
893 * to be used instead of the weak predefined callback.
894 * @param hsai SAI handle.
895 * @param CallbackID ID of the callback to be registered.
896 * This parameter can be one of the following values:
897 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
898 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
899 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
900 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
901 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
902 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
903 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
904 * @param pCallback pointer to the callback function.
905 * @retval HAL status.
907 HAL_StatusTypeDef
HAL_SAI_RegisterCallback(SAI_HandleTypeDef
*hsai
,
908 HAL_SAI_CallbackIDTypeDef CallbackID
,
909 pSAI_CallbackTypeDef pCallback
)
911 HAL_StatusTypeDef status
= HAL_OK
;
913 if (pCallback
== NULL
)
915 /* update the error code */
916 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
917 /* update return status */
922 if (HAL_SAI_STATE_READY
== hsai
->State
)
926 case HAL_SAI_RX_COMPLETE_CB_ID
:
927 hsai
->RxCpltCallback
= pCallback
;
929 case HAL_SAI_RX_HALFCOMPLETE_CB_ID
:
930 hsai
->RxHalfCpltCallback
= pCallback
;
932 case HAL_SAI_TX_COMPLETE_CB_ID
:
933 hsai
->TxCpltCallback
= pCallback
;
935 case HAL_SAI_TX_HALFCOMPLETE_CB_ID
:
936 hsai
->TxHalfCpltCallback
= pCallback
;
938 case HAL_SAI_ERROR_CB_ID
:
939 hsai
->ErrorCallback
= pCallback
;
941 case HAL_SAI_MSPINIT_CB_ID
:
942 hsai
->MspInitCallback
= pCallback
;
944 case HAL_SAI_MSPDEINIT_CB_ID
:
945 hsai
->MspDeInitCallback
= pCallback
;
948 /* update the error code */
949 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
950 /* update return status */
955 else if (HAL_SAI_STATE_RESET
== hsai
->State
)
959 case HAL_SAI_MSPINIT_CB_ID
:
960 hsai
->MspInitCallback
= pCallback
;
962 case HAL_SAI_MSPDEINIT_CB_ID
:
963 hsai
->MspDeInitCallback
= pCallback
;
966 /* update the error code */
967 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
968 /* update return status */
975 /* update the error code */
976 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
977 /* update return status */
985 * @brief Unregister a user SAI callback.
986 * SAI callback is redirected to the weak predefined callback.
987 * @param hsai SAI handle.
988 * @param CallbackID ID of the callback to be unregistered.
989 * This parameter can be one of the following values:
990 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
991 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
992 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
993 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
994 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
995 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
996 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
997 * @retval HAL status.
999 HAL_StatusTypeDef
HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef
*hsai
,
1000 HAL_SAI_CallbackIDTypeDef CallbackID
)
1002 HAL_StatusTypeDef status
= HAL_OK
;
1004 if (HAL_SAI_STATE_READY
== hsai
->State
)
1008 case HAL_SAI_RX_COMPLETE_CB_ID
:
1009 hsai
->RxCpltCallback
= HAL_SAI_RxCpltCallback
;
1011 case HAL_SAI_RX_HALFCOMPLETE_CB_ID
:
1012 hsai
->RxHalfCpltCallback
= HAL_SAI_RxHalfCpltCallback
;
1014 case HAL_SAI_TX_COMPLETE_CB_ID
:
1015 hsai
->TxCpltCallback
= HAL_SAI_TxCpltCallback
;
1017 case HAL_SAI_TX_HALFCOMPLETE_CB_ID
:
1018 hsai
->TxHalfCpltCallback
= HAL_SAI_TxHalfCpltCallback
;
1020 case HAL_SAI_ERROR_CB_ID
:
1021 hsai
->ErrorCallback
= HAL_SAI_ErrorCallback
;
1023 case HAL_SAI_MSPINIT_CB_ID
:
1024 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
1026 case HAL_SAI_MSPDEINIT_CB_ID
:
1027 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
1030 /* update the error code */
1031 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1032 /* update return status */
1037 else if (HAL_SAI_STATE_RESET
== hsai
->State
)
1041 case HAL_SAI_MSPINIT_CB_ID
:
1042 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
1044 case HAL_SAI_MSPDEINIT_CB_ID
:
1045 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
1048 /* update the error code */
1049 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1050 /* update return status */
1057 /* update the error code */
1058 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1059 /* update return status */
1064 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1070 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
1071 * @brief Data transfers functions
1074 ==============================================================================
1075 ##### IO operation functions #####
1076 ==============================================================================
1078 This subsection provides a set of functions allowing to manage the SAI data
1081 (+) There are two modes of transfer:
1082 (++) Blocking mode : The communication is performed in the polling mode.
1083 The status of all data processing is returned by the same function
1084 after finishing transfer.
1085 (++) No-Blocking mode : The communication is performed using Interrupts
1086 or DMA. These functions return the status of the transfer startup.
1087 The end of the data processing will be indicated through the
1088 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
1091 (+) Blocking mode functions are :
1092 (++) HAL_SAI_Transmit()
1093 (++) HAL_SAI_Receive()
1095 (+) Non Blocking mode functions with Interrupt are :
1096 (++) HAL_SAI_Transmit_IT()
1097 (++) HAL_SAI_Receive_IT()
1099 (+) Non Blocking mode functions with DMA are :
1100 (++) HAL_SAI_Transmit_DMA()
1101 (++) HAL_SAI_Receive_DMA()
1103 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1104 (++) HAL_SAI_TxCpltCallback()
1105 (++) HAL_SAI_RxCpltCallback()
1106 (++) HAL_SAI_ErrorCallback()
1113 * @brief Transmit an amount of data in blocking mode.
1114 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1115 * the configuration information for SAI module.
1116 * @param pData Pointer to data buffer
1117 * @param Size Amount of data to be sent
1118 * @param Timeout Timeout duration
1119 * @retval HAL status
1121 HAL_StatusTypeDef
HAL_SAI_Transmit(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
, uint32_t Timeout
)
1123 uint32_t tickstart
= HAL_GetTick();
1126 if ((pData
== NULL
) || (Size
== 0U))
1131 if (hsai
->State
== HAL_SAI_STATE_READY
)
1133 /* Process Locked */
1136 hsai
->XferSize
= Size
;
1137 hsai
->XferCount
= Size
;
1138 hsai
->pBuffPtr
= pData
;
1139 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1140 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1142 /* Check if the SAI is already enabled */
1143 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1145 /* fill the fifo with data before to enabled the SAI */
1147 /* Enable SAI peripheral */
1148 __HAL_SAI_ENABLE(hsai
);
1151 while (hsai
->XferCount
> 0U)
1153 /* Write data if the FIFO is not full */
1154 if ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_FULL
)
1156 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1158 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
1161 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1163 temp
= (uint32_t)(*hsai
->pBuffPtr
);
1165 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
1167 hsai
->Instance
->DR
= temp
;
1171 temp
= (uint32_t)(*hsai
->pBuffPtr
);
1173 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
1175 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
1177 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
1179 hsai
->Instance
->DR
= temp
;
1185 /* Check for the Timeout */
1186 if ((((HAL_GetTick() - tickstart
) > Timeout
) || (Timeout
== 0U)) && (Timeout
!= HAL_MAX_DELAY
))
1188 /* Update error code */
1189 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1191 /* Clear all the flags */
1192 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1194 /* Disable SAI peripheral */
1195 /* No need to check return value because state update, unlock and error return will be performed later */
1196 (void) SAI_Disable(hsai
);
1198 /* Flush the fifo */
1199 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1201 /* Change the SAI state */
1202 hsai
->State
= HAL_SAI_STATE_READY
;
1204 /* Process Unlocked */
1212 hsai
->State
= HAL_SAI_STATE_READY
;
1214 /* Process Unlocked */
1226 * @brief Receive an amount of data in blocking mode.
1227 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1228 * the configuration information for SAI module.
1229 * @param pData Pointer to data buffer
1230 * @param Size Amount of data to be received
1231 * @param Timeout Timeout duration
1232 * @retval HAL status
1234 HAL_StatusTypeDef
HAL_SAI_Receive(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
, uint32_t Timeout
)
1236 uint32_t tickstart
= HAL_GetTick();
1239 if ((pData
== NULL
) || (Size
== 0U))
1244 if (hsai
->State
== HAL_SAI_STATE_READY
)
1246 /* Process Locked */
1249 hsai
->pBuffPtr
= pData
;
1250 hsai
->XferSize
= Size
;
1251 hsai
->XferCount
= Size
;
1252 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1253 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1255 /* Check if the SAI is already enabled */
1256 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1258 /* Enable SAI peripheral */
1259 __HAL_SAI_ENABLE(hsai
);
1263 while (hsai
->XferCount
> 0U)
1265 if ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_EMPTY
)
1267 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1269 *hsai
->pBuffPtr
= (uint8_t)hsai
->Instance
->DR
;
1272 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1274 temp
= hsai
->Instance
->DR
;
1275 *hsai
->pBuffPtr
= (uint8_t)temp
;
1277 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
1282 temp
= hsai
->Instance
->DR
;
1283 *hsai
->pBuffPtr
= (uint8_t)temp
;
1285 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
1287 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 16);
1289 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 24);
1296 /* Check for the Timeout */
1297 if ((((HAL_GetTick() - tickstart
) > Timeout
) || (Timeout
== 0U)) && (Timeout
!= HAL_MAX_DELAY
))
1299 /* Update error code */
1300 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1302 /* Clear all the flags */
1303 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1305 /* Disable SAI peripheral */
1306 /* No need to check return value because state update, unlock and error return will be performed later */
1307 (void) SAI_Disable(hsai
);
1309 /* Flush the fifo */
1310 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1312 /* Change the SAI state */
1313 hsai
->State
= HAL_SAI_STATE_READY
;
1315 /* Process Unlocked */
1323 hsai
->State
= HAL_SAI_STATE_READY
;
1325 /* Process Unlocked */
1337 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1338 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1339 * the configuration information for SAI module.
1340 * @param pData Pointer to data buffer
1341 * @param Size Amount of data to be sent
1342 * @retval HAL status
1344 HAL_StatusTypeDef
HAL_SAI_Transmit_IT(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1346 if ((pData
== NULL
) || (Size
== 0U))
1351 if (hsai
->State
== HAL_SAI_STATE_READY
)
1353 /* Process Locked */
1356 hsai
->pBuffPtr
= pData
;
1357 hsai
->XferSize
= Size
;
1358 hsai
->XferCount
= Size
;
1359 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1360 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1362 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1364 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT8Bit
;
1366 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1368 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT16Bit
;
1372 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT32Bit
;
1375 /* Fill the fifo before starting the communication */
1378 /* Enable FRQ and OVRUDR interrupts */
1379 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
1381 /* Check if the SAI is already enabled */
1382 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1384 /* Enable SAI peripheral */
1385 __HAL_SAI_ENABLE(hsai
);
1387 /* Process Unlocked */
1399 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1400 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1401 * the configuration information for SAI module.
1402 * @param pData Pointer to data buffer
1403 * @param Size Amount of data to be received
1404 * @retval HAL status
1406 HAL_StatusTypeDef
HAL_SAI_Receive_IT(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1408 if ((pData
== NULL
) || (Size
== 0U))
1413 if (hsai
->State
== HAL_SAI_STATE_READY
)
1415 /* Process Locked */
1418 hsai
->pBuffPtr
= pData
;
1419 hsai
->XferSize
= Size
;
1420 hsai
->XferCount
= Size
;
1421 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1422 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1424 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1426 hsai
->InterruptServiceRoutine
= SAI_Receive_IT8Bit
;
1428 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1430 hsai
->InterruptServiceRoutine
= SAI_Receive_IT16Bit
;
1434 hsai
->InterruptServiceRoutine
= SAI_Receive_IT32Bit
;
1437 /* Enable TXE and OVRUDR interrupts */
1438 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
1440 /* Check if the SAI is already enabled */
1441 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1443 /* Enable SAI peripheral */
1444 __HAL_SAI_ENABLE(hsai
);
1447 /* Process Unlocked */
1459 * @brief Pause the audio stream playing from the Media.
1460 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1461 * the configuration information for SAI module.
1462 * @retval HAL status
1464 HAL_StatusTypeDef
HAL_SAI_DMAPause(SAI_HandleTypeDef
*hsai
)
1466 /* Process Locked */
1469 /* Pause the audio file playing by disabling the SAI DMA requests */
1470 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1472 /* Process Unlocked */
1479 * @brief Resume the audio stream playing from the Media.
1480 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1481 * the configuration information for SAI module.
1482 * @retval HAL status
1484 HAL_StatusTypeDef
HAL_SAI_DMAResume(SAI_HandleTypeDef
*hsai
)
1486 /* Process Locked */
1489 /* Enable the SAI DMA requests */
1490 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1492 /* If the SAI peripheral is still not enabled, enable it */
1493 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1495 /* Enable SAI peripheral */
1496 __HAL_SAI_ENABLE(hsai
);
1499 /* Process Unlocked */
1506 * @brief Stop the audio stream playing from the Media.
1507 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1508 * the configuration information for SAI module.
1509 * @retval HAL status
1511 HAL_StatusTypeDef
HAL_SAI_DMAStop(SAI_HandleTypeDef
*hsai
)
1513 HAL_StatusTypeDef status
= HAL_OK
;
1515 /* Process Locked */
1518 /* Disable the SAI DMA request */
1519 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1521 /* Abort the SAI Tx DMA Stream */
1522 if ((hsai
->State
== HAL_SAI_STATE_BUSY_TX
) && (hsai
->hdmatx
!= NULL
))
1524 if (HAL_DMA_Abort(hsai
->hdmatx
) != HAL_OK
)
1526 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1527 if (hsai
->hdmatx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1530 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1535 /* Abort the SAI Rx DMA Stream */
1536 if ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) && (hsai
->hdmarx
!= NULL
))
1538 if (HAL_DMA_Abort(hsai
->hdmarx
) != HAL_OK
)
1540 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1541 if (hsai
->hdmarx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1544 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1549 /* Disable SAI peripheral */
1550 if (SAI_Disable(hsai
) != HAL_OK
)
1555 /* Flush the fifo */
1556 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1558 /* Set hsai state to ready */
1559 hsai
->State
= HAL_SAI_STATE_READY
;
1561 /* Process Unlocked */
1568 * @brief Abort the current transfer and disable the SAI.
1569 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1570 * the configuration information for SAI module.
1571 * @retval HAL status
1573 HAL_StatusTypeDef
HAL_SAI_Abort(SAI_HandleTypeDef
*hsai
)
1575 HAL_StatusTypeDef status
= HAL_OK
;
1577 /* Process Locked */
1580 /* Check SAI DMA is enabled or not */
1581 if ((hsai
->Instance
->CR1
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
1583 /* Disable the SAI DMA request */
1584 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1586 /* Abort the SAI Tx DMA Stream */
1587 if ((hsai
->State
== HAL_SAI_STATE_BUSY_TX
)&& (hsai
->hdmatx
!= NULL
))
1589 if (HAL_DMA_Abort(hsai
->hdmatx
) != HAL_OK
)
1591 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1592 if (hsai
->hdmatx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1595 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1600 /* Abort the SAI Rx DMA Stream */
1601 if ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) && (hsai
->hdmarx
!= NULL
))
1603 if (HAL_DMA_Abort(hsai
->hdmarx
) != HAL_OK
)
1605 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1606 if (hsai
->hdmarx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1609 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1615 /* Disabled All interrupt and clear all the flag */
1616 hsai
->Instance
->IMR
= 0;
1617 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1619 /* Disable SAI peripheral */
1620 if (SAI_Disable(hsai
) != HAL_OK
)
1625 /* Flush the fifo */
1626 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1628 /* Set hsai state to ready */
1629 hsai
->State
= HAL_SAI_STATE_READY
;
1631 /* Process Unlocked */
1638 * @brief Transmit an amount of data in non-blocking mode with DMA.
1639 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1640 * the configuration information for SAI module.
1641 * @param pData Pointer to data buffer
1642 * @param Size Amount of data to be sent
1643 * @retval HAL status
1645 HAL_StatusTypeDef
HAL_SAI_Transmit_DMA(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1647 uint32_t tickstart
= HAL_GetTick();
1649 if ((pData
== NULL
) || (Size
== 0U))
1654 if (hsai
->State
== HAL_SAI_STATE_READY
)
1656 /* Process Locked */
1659 hsai
->pBuffPtr
= pData
;
1660 hsai
->XferSize
= Size
;
1661 hsai
->XferCount
= Size
;
1662 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1663 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1665 /* Set the SAI Tx DMA Half transfer complete callback */
1666 hsai
->hdmatx
->XferHalfCpltCallback
= SAI_DMATxHalfCplt
;
1668 /* Set the SAI TxDMA transfer complete callback */
1669 hsai
->hdmatx
->XferCpltCallback
= SAI_DMATxCplt
;
1671 /* Set the DMA error callback */
1672 hsai
->hdmatx
->XferErrorCallback
= SAI_DMAError
;
1674 /* Set the DMA Tx abort callback */
1675 hsai
->hdmatx
->XferAbortCallback
= NULL
;
1677 /* Enable the Tx DMA Stream */
1678 if (HAL_DMA_Start_IT(hsai
->hdmatx
, (uint32_t)hsai
->pBuffPtr
, (uint32_t)&hsai
->Instance
->DR
, hsai
->XferSize
) != HAL_OK
)
1684 /* Enable the interrupts for error handling */
1685 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
1687 /* Enable SAI Tx DMA Request */
1688 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1690 /* Wait untill FIFO is not empty */
1691 while ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) == SAI_FIFOSTATUS_EMPTY
)
1693 /* Check for the Timeout */
1694 if ((HAL_GetTick() - tickstart
) > SAI_LONG_TIMEOUT
)
1696 /* Update error code */
1697 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1699 /* Process Unlocked */
1706 /* Check if the SAI is already enabled */
1707 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1709 /* Enable SAI peripheral */
1710 __HAL_SAI_ENABLE(hsai
);
1713 /* Process Unlocked */
1725 * @brief Receive an amount of data in non-blocking mode with DMA.
1726 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1727 * the configuration information for SAI module.
1728 * @param pData Pointer to data buffer
1729 * @param Size Amount of data to be received
1730 * @retval HAL status
1732 HAL_StatusTypeDef
HAL_SAI_Receive_DMA(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1735 if ((pData
== NULL
) || (Size
== 0U))
1740 if (hsai
->State
== HAL_SAI_STATE_READY
)
1742 /* Process Locked */
1745 hsai
->pBuffPtr
= pData
;
1746 hsai
->XferSize
= Size
;
1747 hsai
->XferCount
= Size
;
1748 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1749 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1751 /* Set the SAI Rx DMA Half transfer complete callback */
1752 hsai
->hdmarx
->XferHalfCpltCallback
= SAI_DMARxHalfCplt
;
1754 /* Set the SAI Rx DMA transfer complete callback */
1755 hsai
->hdmarx
->XferCpltCallback
= SAI_DMARxCplt
;
1757 /* Set the DMA error callback */
1758 hsai
->hdmarx
->XferErrorCallback
= SAI_DMAError
;
1760 /* Set the DMA Rx abort callback */
1761 hsai
->hdmarx
->XferAbortCallback
= NULL
;
1763 /* Enable the Rx DMA Stream */
1764 if (HAL_DMA_Start_IT(hsai
->hdmarx
, (uint32_t)&hsai
->Instance
->DR
, (uint32_t)hsai
->pBuffPtr
, hsai
->XferSize
) != HAL_OK
)
1770 /* Enable the interrupts for error handling */
1771 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
1773 /* Enable SAI Rx DMA Request */
1774 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1776 /* Check if the SAI is already enabled */
1777 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1779 /* Enable SAI peripheral */
1780 __HAL_SAI_ENABLE(hsai
);
1783 /* Process Unlocked */
1795 * @brief Enable the Tx mute mode.
1796 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1797 * the configuration information for SAI module.
1798 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1799 * @retval HAL status
1801 HAL_StatusTypeDef
HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef
*hsai
, uint16_t val
)
1803 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val
));
1805 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1807 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTEVAL
| SAI_xCR2_MUTE
);
1808 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTE
| (uint32_t)val
);
1815 * @brief Disable the Tx mute mode.
1816 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1817 * the configuration information for SAI module.
1818 * @retval HAL status
1820 HAL_StatusTypeDef
HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef
*hsai
)
1822 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1824 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTEVAL
| SAI_xCR2_MUTE
);
1831 * @brief Enable the Rx mute detection.
1832 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1833 * the configuration information for SAI module.
1834 * @param callback function called when the mute is detected.
1835 * @param counter number a data before mute detection max 63.
1836 * @retval HAL status
1838 HAL_StatusTypeDef
HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef
*hsai
, SAIcallback callback
, uint16_t counter
)
1840 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter
));
1842 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1844 /* set the mute counter */
1845 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTECNT
);
1846 SET_BIT(hsai
->Instance
->CR2
, (uint32_t)((uint32_t)counter
<< SAI_xCR2_MUTECNT_Pos
));
1847 hsai
->mutecallback
= callback
;
1848 /* enable the IT interrupt */
1849 __HAL_SAI_ENABLE_IT(hsai
, SAI_IT_MUTEDET
);
1856 * @brief Disable the Rx mute detection.
1857 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1858 * the configuration information for SAI module.
1859 * @retval HAL status
1861 HAL_StatusTypeDef
HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef
*hsai
)
1863 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1865 /* set the mutecallback to NULL */
1866 hsai
->mutecallback
= NULL
;
1867 /* enable the IT interrupt */
1868 __HAL_SAI_DISABLE_IT(hsai
, SAI_IT_MUTEDET
);
1875 * @brief Handle SAI interrupt request.
1876 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1877 * the configuration information for SAI module.
1880 void HAL_SAI_IRQHandler(SAI_HandleTypeDef
*hsai
)
1882 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1884 uint32_t itflags
= hsai
->Instance
->SR
;
1885 uint32_t itsources
= hsai
->Instance
->IMR
;
1886 uint32_t cr1config
= hsai
->Instance
->CR1
;
1889 /* SAI Fifo request interrupt occured ------------------------------------*/
1890 if (((itflags
& SAI_xSR_FREQ
) == SAI_xSR_FREQ
) && ((itsources
& SAI_IT_FREQ
) == SAI_IT_FREQ
))
1892 hsai
->InterruptServiceRoutine(hsai
);
1894 /* SAI Overrun error interrupt occurred ----------------------------------*/
1895 else if (((itflags
& SAI_FLAG_OVRUDR
) == SAI_FLAG_OVRUDR
) && ((itsources
& SAI_IT_OVRUDR
) == SAI_IT_OVRUDR
))
1897 /* Clear the SAI Overrun flag */
1898 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
1899 /* Get the SAI error code */
1900 tmperror
= ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) ? HAL_SAI_ERROR_OVR
: HAL_SAI_ERROR_UDR
);
1901 /* Change the SAI error code */
1902 hsai
->ErrorCode
|= tmperror
;
1903 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1904 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1905 hsai
->ErrorCallback(hsai
);
1907 HAL_SAI_ErrorCallback(hsai
);
1910 /* SAI mutedet interrupt occurred ----------------------------------*/
1911 else if (((itflags
& SAI_FLAG_MUTEDET
) == SAI_FLAG_MUTEDET
) && ((itsources
& SAI_IT_MUTEDET
) == SAI_IT_MUTEDET
))
1913 /* Clear the SAI mutedet flag */
1914 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_MUTEDET
);
1915 /* call the call back function */
1916 if (hsai
->mutecallback
!= NULL
)
1918 /* inform the user that an RX mute event has been detected */
1919 hsai
->mutecallback();
1922 /* SAI AFSDET interrupt occurred ----------------------------------*/
1923 else if (((itflags
& SAI_FLAG_AFSDET
) == SAI_FLAG_AFSDET
) && ((itsources
& SAI_IT_AFSDET
) == SAI_IT_AFSDET
))
1925 /* Clear the SAI AFSDET flag */
1926 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_AFSDET
);
1928 /* Change the SAI error code */
1929 hsai
->ErrorCode
|= HAL_SAI_ERROR_AFSDET
;
1931 /* Check SAI DMA is enabled or not */
1932 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
1934 /* Abort the SAI DMA Streams */
1935 if (hsai
->hdmatx
!= NULL
)
1937 /* Set the DMA Tx abort callback */
1938 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
1940 /* Abort DMA in IT mode */
1941 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
1943 /* Update SAI error code */
1944 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1946 /* Call SAI error callback */
1947 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1948 hsai
->ErrorCallback(hsai
);
1950 HAL_SAI_ErrorCallback(hsai
);
1954 if (hsai
->hdmarx
!= NULL
)
1956 /* Set the DMA Rx abort callback */
1957 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
1959 /* Abort DMA in IT mode */
1960 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
1962 /* Update SAI error code */
1963 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1965 /* Call SAI error callback */
1966 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1967 hsai
->ErrorCallback(hsai
);
1969 HAL_SAI_ErrorCallback(hsai
);
1977 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1978 (void) HAL_SAI_Abort(hsai
);
1980 /* Set error callback */
1981 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1982 hsai
->ErrorCallback(hsai
);
1984 HAL_SAI_ErrorCallback(hsai
);
1988 /* SAI LFSDET interrupt occurred ----------------------------------*/
1989 else if (((itflags
& SAI_FLAG_LFSDET
) == SAI_FLAG_LFSDET
) && ((itsources
& SAI_IT_LFSDET
) == SAI_IT_LFSDET
))
1991 /* Clear the SAI LFSDET flag */
1992 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_LFSDET
);
1994 /* Change the SAI error code */
1995 hsai
->ErrorCode
|= HAL_SAI_ERROR_LFSDET
;
1997 /* Check SAI DMA is enabled or not */
1998 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
2000 /* Abort the SAI DMA Streams */
2001 if (hsai
->hdmatx
!= NULL
)
2003 /* Set the DMA Tx abort callback */
2004 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
2006 /* Abort DMA in IT mode */
2007 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
2009 /* Update SAI error code */
2010 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2012 /* Call SAI error callback */
2013 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2014 hsai
->ErrorCallback(hsai
);
2016 HAL_SAI_ErrorCallback(hsai
);
2020 if (hsai
->hdmarx
!= NULL
)
2022 /* Set the DMA Rx abort callback */
2023 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
2025 /* Abort DMA in IT mode */
2026 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
2028 /* Update SAI error code */
2029 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2031 /* Call SAI error callback */
2032 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2033 hsai
->ErrorCallback(hsai
);
2035 HAL_SAI_ErrorCallback(hsai
);
2043 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
2044 (void) HAL_SAI_Abort(hsai
);
2046 /* Set error callback */
2047 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2048 hsai
->ErrorCallback(hsai
);
2050 HAL_SAI_ErrorCallback(hsai
);
2054 /* SAI WCKCFG interrupt occurred ----------------------------------*/
2055 else if (((itflags
& SAI_FLAG_WCKCFG
) == SAI_FLAG_WCKCFG
) && ((itsources
& SAI_IT_WCKCFG
) == SAI_IT_WCKCFG
))
2057 /* Clear the SAI WCKCFG flag */
2058 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_WCKCFG
);
2060 /* Change the SAI error code */
2061 hsai
->ErrorCode
|= HAL_SAI_ERROR_WCKCFG
;
2063 /* Check SAI DMA is enabled or not */
2064 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
2066 /* Abort the SAI DMA Streams */
2067 if (hsai
->hdmatx
!= NULL
)
2069 /* Set the DMA Tx abort callback */
2070 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
2072 /* Abort DMA in IT mode */
2073 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
2075 /* Update SAI error code */
2076 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2078 /* Call SAI error callback */
2079 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2080 hsai
->ErrorCallback(hsai
);
2082 HAL_SAI_ErrorCallback(hsai
);
2086 if (hsai
->hdmarx
!= NULL
)
2088 /* Set the DMA Rx abort callback */
2089 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
2091 /* Abort DMA in IT mode */
2092 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
2094 /* Update SAI error code */
2095 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2097 /* Call SAI error callback */
2098 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2099 hsai
->ErrorCallback(hsai
);
2101 HAL_SAI_ErrorCallback(hsai
);
2108 /* If WCKCFG occurs, SAI audio block is automatically disabled */
2109 /* Disable all interrupts and clear all flags */
2110 hsai
->Instance
->IMR
= 0U;
2111 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
2112 /* Set the SAI state to ready to be able to start again the process */
2113 hsai
->State
= HAL_SAI_STATE_READY
;
2115 /* Initialize XferCount */
2116 hsai
->XferCount
= 0U;
2118 /* SAI error Callback */
2119 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2120 hsai
->ErrorCallback(hsai
);
2122 HAL_SAI_ErrorCallback(hsai
);
2126 /* SAI CNRDY interrupt occurred ----------------------------------*/
2127 else if (((itflags
& SAI_FLAG_CNRDY
) == SAI_FLAG_CNRDY
) && ((itsources
& SAI_IT_CNRDY
) == SAI_IT_CNRDY
))
2129 /* Clear the SAI CNRDY flag */
2130 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_CNRDY
);
2131 /* Change the SAI error code */
2132 hsai
->ErrorCode
|= HAL_SAI_ERROR_CNREADY
;
2133 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
2134 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2135 hsai
->ErrorCallback(hsai
);
2137 HAL_SAI_ErrorCallback(hsai
);
2148 * @brief Tx Transfer completed callback.
2149 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2150 * the configuration information for SAI module.
2153 __weak
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef
*hsai
)
2155 /* Prevent unused argument(s) compilation warning */
2158 /* NOTE : This function should not be modified, when the callback is needed,
2159 the HAL_SAI_TxCpltCallback could be implemented in the user file
2164 * @brief Tx Transfer Half completed callback.
2165 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2166 * the configuration information for SAI module.
2169 __weak
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef
*hsai
)
2171 /* Prevent unused argument(s) compilation warning */
2174 /* NOTE : This function should not be modified, when the callback is needed,
2175 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2180 * @brief Rx Transfer completed callback.
2181 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2182 * the configuration information for SAI module.
2185 __weak
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef
*hsai
)
2187 /* Prevent unused argument(s) compilation warning */
2190 /* NOTE : This function should not be modified, when the callback is needed,
2191 the HAL_SAI_RxCpltCallback could be implemented in the user file
2196 * @brief Rx Transfer half completed callback.
2197 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2198 * the configuration information for SAI module.
2201 __weak
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef
*hsai
)
2203 /* Prevent unused argument(s) compilation warning */
2206 /* NOTE : This function should not be modified, when the callback is needed,
2207 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2212 * @brief SAI error callback.
2213 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2214 * the configuration information for SAI module.
2217 __weak
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef
*hsai
)
2219 /* Prevent unused argument(s) compilation warning */
2222 /* NOTE : This function should not be modified, when the callback is needed,
2223 the HAL_SAI_ErrorCallback could be implemented in the user file
2231 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2232 * @brief Peripheral State functions
2235 ===============================================================================
2236 ##### Peripheral State and Errors functions #####
2237 ===============================================================================
2239 This subsection permits to get in run-time the status of the peripheral
2247 * @brief Return the SAI handle state.
2248 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2249 * the configuration information for SAI module.
2252 HAL_SAI_StateTypeDef
HAL_SAI_GetState(SAI_HandleTypeDef
*hsai
)
2258 * @brief Return the SAI error code.
2259 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2260 * the configuration information for the specified SAI Block.
2261 * @retval SAI Error Code
2263 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef
*hsai
)
2265 return hsai
->ErrorCode
;
2276 /** @addtogroup SAI_Private_Functions
2277 * @brief Private functions
2282 * @brief Initialize the SAI I2S protocol according to the specified parameters
2283 * in the SAI_InitTypeDef and create the associated handle.
2284 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2285 * the configuration information for SAI module.
2286 * @param protocol one of the supported protocol.
2287 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2288 * @param nbslot number of slot minimum value is 2 and max is 16.
2289 * the value must be a multiple of 2.
2290 * @retval HAL status
2292 static HAL_StatusTypeDef
SAI_InitI2S(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
2294 HAL_StatusTypeDef status
= HAL_OK
;
2296 hsai
->Init
.Protocol
= SAI_FREE_PROTOCOL
;
2297 hsai
->Init
.FirstBit
= SAI_FIRSTBIT_MSB
;
2298 /* Compute ClockStrobing according AudioMode */
2299 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2302 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_FALLINGEDGE
;
2307 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_RISINGEDGE
;
2309 hsai
->FrameInit
.FSDefinition
= SAI_FS_CHANNEL_IDENTIFICATION
;
2310 hsai
->SlotInit
.SlotActive
= SAI_SLOTACTIVE_ALL
;
2311 hsai
->SlotInit
.FirstBitOffset
= 0;
2312 hsai
->SlotInit
.SlotNumber
= nbslot
;
2314 /* in IS2 the number of slot must be even */
2315 if ((nbslot
& 0x1U
) != 0U)
2320 if (protocol
== SAI_I2S_STANDARD
)
2322 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_LOW
;
2323 hsai
->FrameInit
.FSOffset
= SAI_FS_BEFOREFIRSTBIT
;
2327 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2328 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_HIGH
;
2329 hsai
->FrameInit
.FSOffset
= SAI_FS_FIRSTBIT
;
2332 /* Frame definition */
2335 case SAI_PROTOCOL_DATASIZE_16BIT
:
2336 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2337 hsai
->FrameInit
.FrameLength
= 32U * (nbslot
/ 2U);
2338 hsai
->FrameInit
.ActiveFrameLength
= 16U * (nbslot
/ 2U);
2339 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_16B
;
2341 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED
:
2342 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2343 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2344 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2345 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2347 case SAI_PROTOCOL_DATASIZE_24BIT
:
2348 hsai
->Init
.DataSize
= SAI_DATASIZE_24
;
2349 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2350 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2351 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2353 case SAI_PROTOCOL_DATASIZE_32BIT
:
2354 hsai
->Init
.DataSize
= SAI_DATASIZE_32
;
2355 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2356 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2357 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2363 if (protocol
== SAI_I2S_LSBJUSTIFIED
)
2365 if (datasize
== SAI_PROTOCOL_DATASIZE_16BITEXTENDED
)
2367 hsai
->SlotInit
.FirstBitOffset
= 16;
2369 if (datasize
== SAI_PROTOCOL_DATASIZE_24BIT
)
2371 hsai
->SlotInit
.FirstBitOffset
= 8;
2378 * @brief Initialize the SAI PCM protocol according to the specified parameters
2379 * in the SAI_InitTypeDef and create the associated handle.
2380 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2381 * the configuration information for SAI module.
2382 * @param protocol one of the supported protocol
2383 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2384 * @param nbslot number of slot minimum value is 1 and the max is 16.
2385 * @retval HAL status
2387 static HAL_StatusTypeDef
SAI_InitPCM(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
2389 HAL_StatusTypeDef status
= HAL_OK
;
2391 hsai
->Init
.Protocol
= SAI_FREE_PROTOCOL
;
2392 hsai
->Init
.FirstBit
= SAI_FIRSTBIT_MSB
;
2393 /* Compute ClockStrobing according AudioMode */
2394 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2397 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_RISINGEDGE
;
2402 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_FALLINGEDGE
;
2404 hsai
->FrameInit
.FSDefinition
= SAI_FS_STARTFRAME
;
2405 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_HIGH
;
2406 hsai
->FrameInit
.FSOffset
= SAI_FS_BEFOREFIRSTBIT
;
2407 hsai
->SlotInit
.FirstBitOffset
= 0;
2408 hsai
->SlotInit
.SlotNumber
= nbslot
;
2409 hsai
->SlotInit
.SlotActive
= SAI_SLOTACTIVE_ALL
;
2411 if (protocol
== SAI_PCM_SHORT
)
2413 hsai
->FrameInit
.ActiveFrameLength
= 1;
2418 hsai
->FrameInit
.ActiveFrameLength
= 13;
2423 case SAI_PROTOCOL_DATASIZE_16BIT
:
2424 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2425 hsai
->FrameInit
.FrameLength
= 16U * nbslot
;
2426 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_16B
;
2428 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED
:
2429 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2430 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2431 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2433 case SAI_PROTOCOL_DATASIZE_24BIT
:
2434 hsai
->Init
.DataSize
= SAI_DATASIZE_24
;
2435 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2436 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2438 case SAI_PROTOCOL_DATASIZE_32BIT
:
2439 hsai
->Init
.DataSize
= SAI_DATASIZE_32
;
2440 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2441 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2452 * @brief Fill the fifo.
2453 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2454 * the configuration information for SAI module.
2457 static void SAI_FillFifo(SAI_HandleTypeDef
*hsai
)
2461 /* fill the fifo with data before to enabled the SAI */
2462 while (((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_FULL
) && (hsai
->XferCount
> 0U))
2464 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
2466 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
2469 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
2471 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2473 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2475 hsai
->Instance
->DR
= temp
;
2479 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2481 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2483 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
2485 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
2487 hsai
->Instance
->DR
= temp
;
2494 * @brief Return the interrupt flag to set according the SAI setup.
2495 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2496 * the configuration information for SAI module.
2497 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2498 * @retval the list of the IT flag to enable
2500 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef
*hsai
, SAI_ModeTypedef mode
)
2502 uint32_t tmpIT
= SAI_IT_OVRUDR
;
2504 if (mode
== SAI_MODE_IT
)
2506 tmpIT
|= SAI_IT_FREQ
;
2509 if ((hsai
->Init
.Protocol
== SAI_AC97_PROTOCOL
) &&
2510 ((hsai
->Init
.AudioMode
== SAI_MODESLAVE_RX
) || (hsai
->Init
.AudioMode
== SAI_MODEMASTER_RX
)))
2512 tmpIT
|= SAI_IT_CNRDY
;
2515 if ((hsai
->Init
.AudioMode
== SAI_MODESLAVE_RX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2517 tmpIT
|= SAI_IT_AFSDET
| SAI_IT_LFSDET
;
2521 /* hsai has been configured in master mode */
2522 tmpIT
|= SAI_IT_WCKCFG
;
2528 * @brief Disable the SAI and wait for the disabling.
2529 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2530 * the configuration information for SAI module.
2533 static HAL_StatusTypeDef
SAI_Disable(SAI_HandleTypeDef
*hsai
)
2535 uint32_t count
= SAI_DEFAULT_TIMEOUT
* (SystemCoreClock
/ 7U / 1000U);
2536 HAL_StatusTypeDef status
= HAL_OK
;
2538 /* Disable the SAI instance */
2539 __HAL_SAI_DISABLE(hsai
);
2543 /* Check for the Timeout */
2546 /* Update error code */
2547 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
2548 status
= HAL_TIMEOUT
;
2553 while ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) != 0U);
2559 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2560 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2561 * the configuration information for SAI module.
2564 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef
*hsai
)
2566 if (hsai
->XferCount
== 0U)
2568 /* Handle the end of the transmission */
2569 /* Disable FREQ and OVRUDR interrupts */
2570 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2571 hsai
->State
= HAL_SAI_STATE_READY
;
2572 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2573 hsai
->TxCpltCallback(hsai
);
2575 HAL_SAI_TxCpltCallback(hsai
);
2580 /* Write data on DR register */
2581 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
2588 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2589 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2590 * the configuration information for SAI module.
2593 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef
*hsai
)
2595 if (hsai
->XferCount
== 0U)
2597 /* Handle the end of the transmission */
2598 /* Disable FREQ and OVRUDR interrupts */
2599 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2600 hsai
->State
= HAL_SAI_STATE_READY
;
2601 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2602 hsai
->TxCpltCallback(hsai
);
2604 HAL_SAI_TxCpltCallback(hsai
);
2609 /* Write data on DR register */
2611 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2613 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2615 hsai
->Instance
->DR
= temp
;
2621 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2622 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2623 * the configuration information for SAI module.
2626 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef
*hsai
)
2628 if (hsai
->XferCount
== 0U)
2630 /* Handle the end of the transmission */
2631 /* Disable FREQ and OVRUDR interrupts */
2632 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2633 hsai
->State
= HAL_SAI_STATE_READY
;
2634 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2635 hsai
->TxCpltCallback(hsai
);
2637 HAL_SAI_TxCpltCallback(hsai
);
2642 /* Write data on DR register */
2644 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2646 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2648 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
2650 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
2652 hsai
->Instance
->DR
= temp
;
2658 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2659 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2660 * the configuration information for SAI module.
2663 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef
*hsai
)
2666 *hsai
->pBuffPtr
= (uint8_t)hsai
->Instance
->DR
;
2670 /* Check end of the transfer */
2671 if (hsai
->XferCount
== 0U)
2673 /* Disable TXE and OVRUDR interrupts */
2674 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2676 /* Clear the SAI Overrun flag */
2677 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2679 hsai
->State
= HAL_SAI_STATE_READY
;
2680 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2681 hsai
->RxCpltCallback(hsai
);
2683 HAL_SAI_RxCpltCallback(hsai
);
2689 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2690 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2691 * the configuration information for SAI module.
2694 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef
*hsai
)
2699 temp
= hsai
->Instance
->DR
;
2700 *hsai
->pBuffPtr
= (uint8_t)temp
;
2702 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
2706 /* Check end of the transfer */
2707 if (hsai
->XferCount
== 0U)
2709 /* Disable TXE and OVRUDR interrupts */
2710 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2712 /* Clear the SAI Overrun flag */
2713 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2715 hsai
->State
= HAL_SAI_STATE_READY
;
2716 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2717 hsai
->RxCpltCallback(hsai
);
2719 HAL_SAI_RxCpltCallback(hsai
);
2725 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2726 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2727 * the configuration information for SAI module.
2730 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef
*hsai
)
2735 temp
= hsai
->Instance
->DR
;
2736 *hsai
->pBuffPtr
= (uint8_t)temp
;
2738 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
2740 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 16);
2742 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 24);
2746 /* Check end of the transfer */
2747 if (hsai
->XferCount
== 0U)
2749 /* Disable TXE and OVRUDR interrupts */
2750 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2752 /* Clear the SAI Overrun flag */
2753 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2755 hsai
->State
= HAL_SAI_STATE_READY
;
2756 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2757 hsai
->RxCpltCallback(hsai
);
2759 HAL_SAI_RxCpltCallback(hsai
);
2765 * @brief DMA SAI transmit process complete callback.
2766 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2767 * the configuration information for the specified DMA module.
2770 static void SAI_DMATxCplt(DMA_HandleTypeDef
*hdma
)
2772 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2774 if (hdma
->Init
.Mode
!= DMA_CIRCULAR
)
2776 hsai
->XferCount
= 0;
2778 /* Disable SAI Tx DMA Request */
2779 hsai
->Instance
->CR1
&= (uint32_t)(~SAI_xCR1_DMAEN
);
2781 /* Stop the interrupts error handling */
2782 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
2784 hsai
->State
= HAL_SAI_STATE_READY
;
2786 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2787 hsai
->TxCpltCallback(hsai
);
2789 HAL_SAI_TxCpltCallback(hsai
);
2794 * @brief DMA SAI transmit process half complete callback.
2795 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2796 * the configuration information for the specified DMA module.
2799 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef
*hdma
)
2801 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2803 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2804 hsai
->TxHalfCpltCallback(hsai
);
2806 HAL_SAI_TxHalfCpltCallback(hsai
);
2811 * @brief DMA SAI receive process complete callback.
2812 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2813 * the configuration information for the specified DMA module.
2816 static void SAI_DMARxCplt(DMA_HandleTypeDef
*hdma
)
2818 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2820 if (hdma
->Init
.Mode
!= DMA_CIRCULAR
)
2822 /* Disable Rx DMA Request */
2823 hsai
->Instance
->CR1
&= (uint32_t)(~SAI_xCR1_DMAEN
);
2824 hsai
->XferCount
= 0;
2826 /* Stop the interrupts error handling */
2827 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
2829 hsai
->State
= HAL_SAI_STATE_READY
;
2831 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2832 hsai
->RxCpltCallback(hsai
);
2834 HAL_SAI_RxCpltCallback(hsai
);
2839 * @brief DMA SAI receive process half complete callback
2840 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2841 * the configuration information for the specified DMA module.
2844 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef
*hdma
)
2846 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2848 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2849 hsai
->RxHalfCpltCallback(hsai
);
2851 HAL_SAI_RxHalfCpltCallback(hsai
);
2856 * @brief DMA SAI communication error callback.
2857 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2858 * the configuration information for the specified DMA module.
2861 static void SAI_DMAError(DMA_HandleTypeDef
*hdma
)
2863 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2865 /* Ignore DMA FIFO error */
2866 if (HAL_DMA_GetError(hdma
) != HAL_DMA_ERROR_FE
)
2868 /* Set SAI error code */
2869 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2871 /* Disable the SAI DMA request */
2872 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
2874 /* Disable SAI peripheral */
2875 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2876 (void) SAI_Disable(hsai
);
2878 /* Set the SAI state ready to be able to start again the process */
2879 hsai
->State
= HAL_SAI_STATE_READY
;
2881 /* Initialize XferCount */
2882 hsai
->XferCount
= 0U;
2884 /* SAI error Callback */
2885 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2886 hsai
->ErrorCallback(hsai
);
2888 HAL_SAI_ErrorCallback(hsai
);
2894 * @brief DMA SAI Abort callback.
2895 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2896 * the configuration information for the specified DMA module.
2899 static void SAI_DMAAbort(DMA_HandleTypeDef
*hdma
)
2901 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2903 /* Disable DMA request */
2904 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
2906 /* Disable all interrupts and clear all flags */
2907 hsai
->Instance
->IMR
= 0U;
2908 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
2910 if (hsai
->ErrorCode
!= HAL_SAI_ERROR_WCKCFG
)
2912 /* Disable SAI peripheral */
2913 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2914 (void) SAI_Disable(hsai
);
2916 /* Flush the fifo */
2917 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
2919 /* Set the SAI state to ready to be able to start again the process */
2920 hsai
->State
= HAL_SAI_STATE_READY
;
2922 /* Initialize XferCount */
2923 hsai
->XferCount
= 0U;
2925 /* SAI error Callback */
2926 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2927 hsai
->ErrorCallback(hsai
);
2929 HAL_SAI_ErrorCallback(hsai
);
2937 #endif /* HAL_SAI_MODULE_ENABLED */
2946 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/