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_FIFO_SIZE 8U
248 #define SAI_DEFAULT_TIMEOUT 4U
249 #define SAI_LONG_TIMEOUT 1000U
254 /* Private macro -------------------------------------------------------------*/
255 /* Private variables ---------------------------------------------------------*/
256 /* Private function prototypes -----------------------------------------------*/
257 /** @defgroup SAI_Private_Functions SAI Private Functions
260 static void SAI_FillFifo(SAI_HandleTypeDef
*hsai
);
261 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef
*hsai
, SAI_ModeTypedef mode
);
262 static HAL_StatusTypeDef
SAI_InitI2S(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
);
263 static HAL_StatusTypeDef
SAI_InitPCM(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
);
265 static HAL_StatusTypeDef
SAI_Disable(SAI_HandleTypeDef
*hsai
);
266 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef
*hsai
);
267 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef
*hsai
);
268 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef
*hsai
);
269 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef
*hsai
);
270 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef
*hsai
);
271 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef
*hsai
);
273 static void SAI_DMATxCplt(DMA_HandleTypeDef
*hdma
);
274 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef
*hdma
);
275 static void SAI_DMARxCplt(DMA_HandleTypeDef
*hdma
);
276 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef
*hdma
);
277 static void SAI_DMAError(DMA_HandleTypeDef
*hdma
);
278 static void SAI_DMAAbort(DMA_HandleTypeDef
*hdma
);
283 /* Exported functions ---------------------------------------------------------*/
284 /** @defgroup SAI_Exported_Functions SAI Exported Functions
288 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
289 * @brief Initialization and Configuration functions
292 ===============================================================================
293 ##### Initialization and de-initialization functions #####
294 ===============================================================================
295 [..] This subsection provides a set of functions allowing to initialize and
296 de-initialize the SAIx peripheral:
298 (+) User must implement HAL_SAI_MspInit() function in which he configures
299 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
301 (+) Call the function HAL_SAI_Init() to configure the selected device with
302 the selected configuration:
303 (++) Mode (Master/slave TX/RX)
313 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
314 of the selected SAI peripheral.
321 * @brief Initialize the structure FrameInit, SlotInit and the low part of
322 * Init according to the specified parameters and call the function
323 * HAL_SAI_Init to initialize the SAI block.
324 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
325 * the configuration information for SAI module.
326 * @param protocol one of the supported protocol @ref SAI_Protocol
327 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
328 * the configuration information for SAI module.
329 * @param nbslot Number of slot.
332 HAL_StatusTypeDef
HAL_SAI_InitProtocol(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
334 HAL_StatusTypeDef status
;
336 /* Check the parameters */
337 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol
));
338 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize
));
342 case SAI_I2S_STANDARD
:
343 case SAI_I2S_MSBJUSTIFIED
:
344 case SAI_I2S_LSBJUSTIFIED
:
345 status
= SAI_InitI2S(hsai
, protocol
, datasize
, nbslot
);
349 status
= SAI_InitPCM(hsai
, protocol
, datasize
, nbslot
);
356 if (status
== HAL_OK
)
358 status
= HAL_SAI_Init(hsai
);
365 * @brief Initialize the SAI according to the specified parameters.
366 * in the SAI_InitTypeDef structure and initialize the associated handle.
367 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
368 * the configuration information for SAI module.
371 HAL_StatusTypeDef
HAL_SAI_Init(SAI_HandleTypeDef
*hsai
)
373 uint32_t tmpregisterGCR
;
375 uint32_t syncen_bits
;
376 SAI_TypeDef
*SaiBaseAddress
;
378 /* Check the SAI handle allocation */
384 /* check the instance */
385 assert_param(IS_SAI_ALL_INSTANCE(hsai
->Instance
));
387 /* Check the SAI Block parameters */
388 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai
->Init
.AudioFrequency
));
389 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai
->Init
.Protocol
));
390 assert_param(IS_SAI_BLOCK_MODE(hsai
->Init
.AudioMode
));
391 assert_param(IS_SAI_BLOCK_DATASIZE(hsai
->Init
.DataSize
));
392 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai
->Init
.FirstBit
));
393 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai
->Init
.ClockStrobing
));
394 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai
->Init
.Synchro
));
395 #if defined(SAI_VER_V2_X)
396 /* SAI Peripheral version depends on STM32H7 device revision ID */
397 if (HAL_GetREVID() >= REV_ID_B
) /* STM32H7xx Rev.B and above */
399 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai
->Init
.MckOutput
));
401 #else /* SAI_VER_V2_1 */
402 assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai
->Init
.MckOutput
));
403 #endif /* SAI_VER_V2_X */
404 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai
->Init
.OutputDrive
));
405 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai
->Init
.NoDivider
));
406 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai
->Init
.FIFOThreshold
));
407 assert_param(IS_SAI_MONO_STEREO_MODE(hsai
->Init
.MonoStereoMode
));
408 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai
->Init
.CompandingMode
));
409 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai
->Init
.TriState
));
410 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai
->Init
.SynchroExt
));
411 assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai
->Init
.MckOverSampling
));
413 /* Check the SAI Block Frame parameters */
414 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai
->FrameInit
.FrameLength
));
415 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai
->FrameInit
.ActiveFrameLength
));
416 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai
->FrameInit
.FSDefinition
));
417 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai
->FrameInit
.FSPolarity
));
418 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai
->FrameInit
.FSOffset
));
420 /* Check the SAI Block Slot parameters */
421 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai
->SlotInit
.FirstBitOffset
));
422 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai
->SlotInit
.SlotSize
));
423 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai
->SlotInit
.SlotNumber
));
424 assert_param(IS_SAI_SLOT_ACTIVE(hsai
->SlotInit
.SlotActive
));
426 /* Check the SAI PDM parameters */
427 assert_param(IS_FUNCTIONAL_STATE(hsai
->Init
.PdmInit
.Activation
));
428 if (hsai
->Init
.PdmInit
.Activation
== ENABLE
)
430 assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai
->Init
.PdmInit
.MicPairsNbr
));
431 assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai
->Init
.PdmInit
.ClockEnable
));
432 /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
434 if (((hsai
->Instance
!= SAI1_Block_A
) && (hsai
->Instance
!= SAI4_Block_A
)) ||
435 (hsai
->Init
.AudioMode
!= SAI_MODEMASTER_RX
) ||
436 (hsai
->Init
.Protocol
!= SAI_FREE_PROTOCOL
))
441 if ((hsai
->Instance
!= SAI1_Block_A
) ||
442 (hsai
->Init
.AudioMode
!= SAI_MODEMASTER_RX
) ||
443 (hsai
->Init
.Protocol
!= SAI_FREE_PROTOCOL
))
450 /* Get the SAI base address according to the SAI handle */
451 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI1_Block_B
))
453 SaiBaseAddress
= SAI1
;
456 else if ((hsai
->Instance
== SAI2_Block_A
) || (hsai
->Instance
== SAI2_Block_B
))
458 SaiBaseAddress
= SAI2
;
462 else if ((hsai
->Instance
== SAI3_Block_A
) || (hsai
->Instance
== SAI3_Block_B
))
464 SaiBaseAddress
= SAI3
;
468 else if ((hsai
->Instance
== SAI4_Block_A
) || (hsai
->Instance
== SAI4_Block_B
))
470 SaiBaseAddress
= SAI4
;
478 if (hsai
->State
== HAL_SAI_STATE_RESET
)
480 /* Allocate lock resource and initialize it */
481 hsai
->Lock
= HAL_UNLOCKED
;
483 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
484 /* Reset callback pointers to the weak predefined callbacks */
485 hsai
->RxCpltCallback
= HAL_SAI_RxCpltCallback
;
486 hsai
->RxHalfCpltCallback
= HAL_SAI_RxHalfCpltCallback
;
487 hsai
->TxCpltCallback
= HAL_SAI_TxCpltCallback
;
488 hsai
->TxHalfCpltCallback
= HAL_SAI_TxHalfCpltCallback
;
489 hsai
->ErrorCallback
= HAL_SAI_ErrorCallback
;
491 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
492 if (hsai
->MspInitCallback
== NULL
)
494 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
496 hsai
->MspInitCallback(hsai
);
498 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
499 HAL_SAI_MspInit(hsai
);
503 /* Disable the selected SAI peripheral */
504 if(SAI_Disable(hsai
) != HAL_OK
)
509 hsai
->State
= HAL_SAI_STATE_BUSY
;
511 /* SAI Block Synchro Configuration -----------------------------------------*/
512 /* This setting must be done with both audio block (A & B) disabled */
513 switch (hsai
->Init
.SynchroExt
)
515 case SAI_SYNCEXT_DISABLE
:
518 case SAI_SYNCEXT_OUTBLOCKA_ENABLE
:
519 tmpregisterGCR
= SAI_GCR_SYNCOUT_0
;
521 case SAI_SYNCEXT_OUTBLOCKB_ENABLE
:
522 tmpregisterGCR
= SAI_GCR_SYNCOUT_1
;
529 switch (hsai
->Init
.Synchro
)
531 case SAI_ASYNCHRONOUS
:
534 case SAI_SYNCHRONOUS
:
535 syncen_bits
= SAI_xCR1_SYNCEN_0
;
537 case SAI_SYNCHRONOUS_EXT_SAI1
:
538 syncen_bits
= SAI_xCR1_SYNCEN_1
;
541 case SAI_SYNCHRONOUS_EXT_SAI2
:
542 syncen_bits
= SAI_xCR1_SYNCEN_1
;
543 tmpregisterGCR
|= SAI_GCR_SYNCIN_0
;
547 case SAI_SYNCHRONOUS_EXT_SAI3
:
548 syncen_bits
= SAI_xCR1_SYNCEN_1
;
549 tmpregisterGCR
|= SAI_GCR_SYNCIN_1
;
553 case SAI_SYNCHRONOUS_EXT_SAI4
:
554 syncen_bits
= SAI_xCR1_SYNCEN_1
;
555 tmpregisterGCR
|= (SAI_GCR_SYNCIN_1
| SAI_GCR_SYNCIN_0
);
563 /* Set the SAI Block Synchro Configuration */
564 SaiBaseAddress
->GCR
= tmpregisterGCR
;
566 if (hsai
->Init
.AudioFrequency
!= SAI_AUDIO_FREQUENCY_MCKDIV
)
571 /* In this case, the MCKDIV value is calculated to get AudioFrequency */
572 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI1_Block_B
))
574 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1
);
578 #if defined(RCC_PERIPHCLK_SAI2)
579 if ((hsai
->Instance
== SAI2_Block_A
) || (hsai
->Instance
== SAI2_Block_B
))
581 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2
);
584 if (hsai
->Instance
== SAI2_Block_A
)
586 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A
);
588 if (hsai
->Instance
== SAI2_Block_B
)
590 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B
);
592 #endif /* RCC_PERIPHCLK_SAI2 */
596 if ((hsai
->Instance
== SAI3_Block_A
) || (hsai
->Instance
== SAI3_Block_B
))
598 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3
);
602 if (hsai
->Instance
== SAI4_Block_A
)
604 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A
);
606 if (hsai
->Instance
== SAI4_Block_B
)
608 freq
= HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B
);
612 /* Configure Master Clock Divider using the following formula :
614 MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
616 MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
617 if (hsai
->Init
.NoDivider
== SAI_MASTERDIVIDER_DISABLE
)
620 /* (freq x 10) to keep Significant digits */
621 tmpval
= (freq
* 10U) / (hsai
->Init
.AudioFrequency
* hsai
->FrameInit
.FrameLength
);
627 tmposr
= (hsai
->Init
.MckOverSampling
== SAI_MCK_OVERSAMPLING_ENABLE
) ? 2U : 1U;
628 /* (freq x 10) to keep Significant digits */
629 tmpval
= (freq
* 10U) / (hsai
->Init
.AudioFrequency
* tmposr
* 256U);
631 hsai
->Init
.Mckdiv
= tmpval
/ 10U;
633 /* Round result to the nearest integer */
634 if ((tmpval
% 10U) > 8U)
636 hsai
->Init
.Mckdiv
+= 1U;
640 /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
641 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
644 ckstr_bits
= (hsai
->Init
.ClockStrobing
== SAI_CLOCKSTROBING_RISINGEDGE
) ? 0U : SAI_xCR1_CKSTR
;
649 ckstr_bits
= (hsai
->Init
.ClockStrobing
== SAI_CLOCKSTROBING_RISINGEDGE
) ? SAI_xCR1_CKSTR
: 0U;
652 /* SAI Block Configuration -------------------------------------------------*/
653 /* SAI CR1 Configuration */
654 #if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
656 if (HAL_GetREVID() >= REV_ID_B
) /* STM32H7xx Rev.B and above */
658 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
659 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
660 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
661 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
| \
664 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
665 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
666 ckstr_bits
| syncen_bits
| \
667 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
668 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
669 hsai
->Init
.MckOverSampling
| hsai
->Init
.MckOutput
);
671 else /* STM32H7xx Rev.Y */
673 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
674 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
675 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
676 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
);
678 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
679 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
680 ckstr_bits
| syncen_bits
| \
681 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
682 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
683 hsai
->Init
.MckOverSampling
);
685 #else /* SAI_VER_V2_1*/
686 hsai
->Instance
->CR1
&= ~(SAI_xCR1_MODE
| SAI_xCR1_PRTCFG
| SAI_xCR1_DS
| \
687 SAI_xCR1_LSBFIRST
| SAI_xCR1_CKSTR
| SAI_xCR1_SYNCEN
| \
688 SAI_xCR1_MONO
| SAI_xCR1_OUTDRIV
| SAI_xCR1_DMAEN
| \
689 SAI_xCR1_NODIV
| SAI_xCR1_MCKDIV
| SAI_xCR1_OSR
| \
692 hsai
->Instance
->CR1
|= (hsai
->Init
.AudioMode
| hsai
->Init
.Protocol
| \
693 hsai
->Init
.DataSize
| hsai
->Init
.FirstBit
| \
694 ckstr_bits
| syncen_bits
| \
695 hsai
->Init
.MonoStereoMode
| hsai
->Init
.OutputDrive
| \
696 hsai
->Init
.NoDivider
| (hsai
->Init
.Mckdiv
<< 20) | \
697 hsai
->Init
.MckOverSampling
| hsai
->Init
.MckOutput
);
698 #endif /* SAI_VER_V2_X */
700 /* SAI CR2 Configuration */
701 hsai
->Instance
->CR2
&= ~(SAI_xCR2_FTH
| SAI_xCR2_FFLUSH
| SAI_xCR2_COMP
| SAI_xCR2_CPL
);
702 hsai
->Instance
->CR2
|= (hsai
->Init
.FIFOThreshold
| hsai
->Init
.CompandingMode
| hsai
->Init
.TriState
);
704 /* SAI Frame Configuration -----------------------------------------*/
705 hsai
->Instance
->FRCR
&= (~(SAI_xFRCR_FRL
| SAI_xFRCR_FSALL
| SAI_xFRCR_FSDEF
| \
706 SAI_xFRCR_FSPOL
| SAI_xFRCR_FSOFF
));
707 hsai
->Instance
->FRCR
|= ((hsai
->FrameInit
.FrameLength
- 1U) |
708 hsai
->FrameInit
.FSOffset
|
709 hsai
->FrameInit
.FSDefinition
|
710 hsai
->FrameInit
.FSPolarity
|
711 ((hsai
->FrameInit
.ActiveFrameLength
- 1U) << 8));
713 /* SAI Block_x SLOT Configuration ------------------------------------------*/
714 /* This register has no meaning in AC 97 and SPDIF audio protocol */
715 hsai
->Instance
->SLOTR
&= (~(SAI_xSLOTR_FBOFF
| SAI_xSLOTR_SLOTSZ
| \
716 SAI_xSLOTR_NBSLOT
| SAI_xSLOTR_SLOTEN
));
718 hsai
->Instance
->SLOTR
|= hsai
->SlotInit
.FirstBitOffset
| hsai
->SlotInit
.SlotSize
| \
719 (hsai
->SlotInit
.SlotActive
<< 16) | ((hsai
->SlotInit
.SlotNumber
- 1U) << 8);
721 /* SAI PDM Configuration ---------------------------------------------------*/
723 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI4_Block_A
))
725 if (hsai
->Instance
== SAI1_Block_A
)
728 /* Disable PDM interface */
729 SaiBaseAddress
->PDMCR
&= ~(SAI_PDMCR_PDMEN
);
730 if (hsai
->Init
.PdmInit
.Activation
== ENABLE
)
732 /* Configure and enable PDM interface */
733 SaiBaseAddress
->PDMCR
= (hsai
->Init
.PdmInit
.ClockEnable
|
734 ((hsai
->Init
.PdmInit
.MicPairsNbr
- 1U) << SAI_PDMCR_MICNBR_Pos
));
735 SaiBaseAddress
->PDMCR
|= SAI_PDMCR_PDMEN
;
739 /* Initialize the error code */
740 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
742 /* Initialize the SAI state */
743 hsai
->State
= HAL_SAI_STATE_READY
;
752 * @brief DeInitialize the SAI peripheral.
753 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
754 * the configuration information for SAI module.
757 HAL_StatusTypeDef
HAL_SAI_DeInit(SAI_HandleTypeDef
*hsai
)
759 SAI_TypeDef
*SaiBaseAddress
;
761 /* Check the SAI handle allocation */
767 hsai
->State
= HAL_SAI_STATE_BUSY
;
769 /* Disabled All interrupt and clear all the flag */
770 hsai
->Instance
->IMR
= 0;
771 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
773 /* Disable the SAI */
774 if (SAI_Disable(hsai
) != HAL_OK
)
776 /* Reset SAI state to ready */
777 hsai
->State
= HAL_SAI_STATE_READY
;
786 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
788 /* Disable SAI PDM interface */
790 if ((hsai
->Instance
== SAI1_Block_A
) || (hsai
->Instance
== SAI4_Block_A
))
792 if (hsai
->Instance
== SAI1_Block_A
)
795 /* Get the SAI base address according to the SAI handle */
797 SaiBaseAddress
= (hsai
->Instance
== SAI1_Block_A
) ? SAI1
: SAI4
;
799 SaiBaseAddress
= SAI1
;
802 /* Reset PDM delays */
803 SaiBaseAddress
->PDMDLY
= 0U;
805 /* Disable PDM interface */
806 SaiBaseAddress
->PDMCR
&= ~(SAI_PDMCR_PDMEN
);
809 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
810 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
811 if (hsai
->MspDeInitCallback
== NULL
)
813 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
815 hsai
->MspDeInitCallback(hsai
);
817 HAL_SAI_MspDeInit(hsai
);
820 /* Initialize the error code */
821 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
823 /* Initialize the SAI state */
824 hsai
->State
= HAL_SAI_STATE_RESET
;
833 * @brief Initialize the SAI MSP.
834 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
835 * the configuration information for SAI module.
838 __weak
void HAL_SAI_MspInit(SAI_HandleTypeDef
*hsai
)
840 /* Prevent unused argument(s) compilation warning */
843 /* NOTE : This function should not be modified, when the callback is needed,
844 the HAL_SAI_MspInit could be implemented in the user file
849 * @brief DeInitialize the SAI MSP.
850 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
851 * the configuration information for SAI module.
854 __weak
void HAL_SAI_MspDeInit(SAI_HandleTypeDef
*hsai
)
856 /* Prevent unused argument(s) compilation warning */
859 /* NOTE : This function should not be modified, when the callback is needed,
860 the HAL_SAI_MspDeInit could be implemented in the user file
864 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
866 * @brief Register a user SAI callback
867 * to be used instead of the weak predefined callback.
868 * @param hsai SAI handle.
869 * @param CallbackID ID of the callback to be registered.
870 * This parameter can be one of the following values:
871 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
872 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
873 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
874 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
875 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
876 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
877 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
878 * @param pCallback pointer to the callback function.
879 * @retval HAL status.
881 HAL_StatusTypeDef
HAL_SAI_RegisterCallback(SAI_HandleTypeDef
*hsai
,
882 HAL_SAI_CallbackIDTypeDef CallbackID
,
883 pSAI_CallbackTypeDef pCallback
)
885 HAL_StatusTypeDef status
= HAL_OK
;
887 if (pCallback
== NULL
)
889 /* update the error code */
890 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
891 /* update return status */
896 if (HAL_SAI_STATE_READY
== hsai
->State
)
900 case HAL_SAI_RX_COMPLETE_CB_ID
:
901 hsai
->RxCpltCallback
= pCallback
;
903 case HAL_SAI_RX_HALFCOMPLETE_CB_ID
:
904 hsai
->RxHalfCpltCallback
= pCallback
;
906 case HAL_SAI_TX_COMPLETE_CB_ID
:
907 hsai
->TxCpltCallback
= pCallback
;
909 case HAL_SAI_TX_HALFCOMPLETE_CB_ID
:
910 hsai
->TxHalfCpltCallback
= pCallback
;
912 case HAL_SAI_ERROR_CB_ID
:
913 hsai
->ErrorCallback
= pCallback
;
915 case HAL_SAI_MSPINIT_CB_ID
:
916 hsai
->MspInitCallback
= pCallback
;
918 case HAL_SAI_MSPDEINIT_CB_ID
:
919 hsai
->MspDeInitCallback
= pCallback
;
922 /* update the error code */
923 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
924 /* update return status */
929 else if (HAL_SAI_STATE_RESET
== hsai
->State
)
933 case HAL_SAI_MSPINIT_CB_ID
:
934 hsai
->MspInitCallback
= pCallback
;
936 case HAL_SAI_MSPDEINIT_CB_ID
:
937 hsai
->MspDeInitCallback
= pCallback
;
940 /* update the error code */
941 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
942 /* update return status */
949 /* update the error code */
950 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
951 /* update return status */
959 * @brief Unregister a user SAI callback.
960 * SAI callback is redirected to the weak predefined callback.
961 * @param hsai SAI handle.
962 * @param CallbackID ID of the callback to be unregistered.
963 * This parameter can be one of the following values:
964 * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
965 * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
966 * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
967 * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
968 * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
969 * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
970 * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
971 * @retval HAL status.
973 HAL_StatusTypeDef
HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef
*hsai
,
974 HAL_SAI_CallbackIDTypeDef CallbackID
)
976 HAL_StatusTypeDef status
= HAL_OK
;
978 if (HAL_SAI_STATE_READY
== hsai
->State
)
982 case HAL_SAI_RX_COMPLETE_CB_ID
:
983 hsai
->RxCpltCallback
= HAL_SAI_RxCpltCallback
;
985 case HAL_SAI_RX_HALFCOMPLETE_CB_ID
:
986 hsai
->RxHalfCpltCallback
= HAL_SAI_RxHalfCpltCallback
;
988 case HAL_SAI_TX_COMPLETE_CB_ID
:
989 hsai
->TxCpltCallback
= HAL_SAI_TxCpltCallback
;
991 case HAL_SAI_TX_HALFCOMPLETE_CB_ID
:
992 hsai
->TxHalfCpltCallback
= HAL_SAI_TxHalfCpltCallback
;
994 case HAL_SAI_ERROR_CB_ID
:
995 hsai
->ErrorCallback
= HAL_SAI_ErrorCallback
;
997 case HAL_SAI_MSPINIT_CB_ID
:
998 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
1000 case HAL_SAI_MSPDEINIT_CB_ID
:
1001 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
1004 /* update the error code */
1005 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1006 /* update return status */
1011 else if (HAL_SAI_STATE_RESET
== hsai
->State
)
1015 case HAL_SAI_MSPINIT_CB_ID
:
1016 hsai
->MspInitCallback
= HAL_SAI_MspInit
;
1018 case HAL_SAI_MSPDEINIT_CB_ID
:
1019 hsai
->MspDeInitCallback
= HAL_SAI_MspDeInit
;
1022 /* update the error code */
1023 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1024 /* update return status */
1031 /* update the error code */
1032 hsai
->ErrorCode
|= HAL_SAI_ERROR_INVALID_CALLBACK
;
1033 /* update return status */
1038 #endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
1044 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
1045 * @brief Data transfers functions
1048 ==============================================================================
1049 ##### IO operation functions #####
1050 ==============================================================================
1052 This subsection provides a set of functions allowing to manage the SAI data
1055 (+) There are two modes of transfer:
1056 (++) Blocking mode : The communication is performed in the polling mode.
1057 The status of all data processing is returned by the same function
1058 after finishing transfer.
1059 (++) No-Blocking mode : The communication is performed using Interrupts
1060 or DMA. These functions return the status of the transfer startup.
1061 The end of the data processing will be indicated through the
1062 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
1065 (+) Blocking mode functions are :
1066 (++) HAL_SAI_Transmit()
1067 (++) HAL_SAI_Receive()
1069 (+) Non Blocking mode functions with Interrupt are :
1070 (++) HAL_SAI_Transmit_IT()
1071 (++) HAL_SAI_Receive_IT()
1073 (+) Non Blocking mode functions with DMA are :
1074 (++) HAL_SAI_Transmit_DMA()
1075 (++) HAL_SAI_Receive_DMA()
1077 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
1078 (++) HAL_SAI_TxCpltCallback()
1079 (++) HAL_SAI_RxCpltCallback()
1080 (++) HAL_SAI_ErrorCallback()
1087 * @brief Transmit an amount of data in blocking mode.
1088 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1089 * the configuration information for SAI module.
1090 * @param pData Pointer to data buffer
1091 * @param Size Amount of data to be sent
1092 * @param Timeout Timeout duration
1093 * @retval HAL status
1095 HAL_StatusTypeDef
HAL_SAI_Transmit(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
, uint32_t Timeout
)
1097 uint32_t tickstart
= HAL_GetTick();
1100 if ((pData
== NULL
) || (Size
== 0U))
1105 if (hsai
->State
== HAL_SAI_STATE_READY
)
1107 /* Process Locked */
1110 hsai
->XferSize
= Size
;
1111 hsai
->XferCount
= Size
;
1112 hsai
->pBuffPtr
= pData
;
1113 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1114 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1116 /* Check if the SAI is already enabled */
1117 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1119 /* fill the fifo with data before to enabled the SAI */
1121 /* Enable SAI peripheral */
1122 __HAL_SAI_ENABLE(hsai
);
1125 while (hsai
->XferCount
> 0U)
1127 /* Write data if the FIFO is not full */
1128 if ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_FULL
)
1130 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1132 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
1135 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1137 temp
= (uint32_t)(*hsai
->pBuffPtr
);
1139 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
1141 hsai
->Instance
->DR
= temp
;
1145 temp
= (uint32_t)(*hsai
->pBuffPtr
);
1147 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
1149 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
1151 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
1153 hsai
->Instance
->DR
= temp
;
1159 /* Check for the Timeout */
1160 if ((((HAL_GetTick() - tickstart
) > Timeout
) || (Timeout
== 0U)) && (Timeout
!= HAL_MAX_DELAY
))
1162 /* Update error code */
1163 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1165 /* Clear all the flags */
1166 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1168 /* Disable SAI peripheral */
1169 /* No need to check return value because state update, unlock and error return will be performed later */
1170 (void) SAI_Disable(hsai
);
1172 /* Flush the fifo */
1173 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1175 /* Change the SAI state */
1176 hsai
->State
= HAL_SAI_STATE_READY
;
1178 /* Process Unlocked */
1186 hsai
->State
= HAL_SAI_STATE_READY
;
1188 /* Process Unlocked */
1200 * @brief Receive an amount of data in blocking mode.
1201 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1202 * the configuration information for SAI module.
1203 * @param pData Pointer to data buffer
1204 * @param Size Amount of data to be received
1205 * @param Timeout Timeout duration
1206 * @retval HAL status
1208 HAL_StatusTypeDef
HAL_SAI_Receive(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
, uint32_t Timeout
)
1210 uint32_t tickstart
= HAL_GetTick();
1213 if ((pData
== NULL
) || (Size
== 0U))
1218 if (hsai
->State
== HAL_SAI_STATE_READY
)
1220 /* Process Locked */
1223 hsai
->pBuffPtr
= pData
;
1224 hsai
->XferSize
= Size
;
1225 hsai
->XferCount
= Size
;
1226 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1227 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1229 /* Check if the SAI is already enabled */
1230 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1232 /* Enable SAI peripheral */
1233 __HAL_SAI_ENABLE(hsai
);
1237 while (hsai
->XferCount
> 0U)
1239 if ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_EMPTY
)
1241 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1243 *hsai
->pBuffPtr
= (uint8_t)hsai
->Instance
->DR
;
1246 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1248 temp
= hsai
->Instance
->DR
;
1249 *hsai
->pBuffPtr
= (uint8_t)temp
;
1251 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
1256 temp
= hsai
->Instance
->DR
;
1257 *hsai
->pBuffPtr
= (uint8_t)temp
;
1259 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
1261 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 16);
1263 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 24);
1270 /* Check for the Timeout */
1271 if ((((HAL_GetTick() - tickstart
) > Timeout
) || (Timeout
== 0U)) && (Timeout
!= HAL_MAX_DELAY
))
1273 /* Update error code */
1274 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1276 /* Clear all the flags */
1277 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1279 /* Disable SAI peripheral */
1280 /* No need to check return value because state update, unlock and error return will be performed later */
1281 (void) SAI_Disable(hsai
);
1283 /* Flush the fifo */
1284 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1286 /* Change the SAI state */
1287 hsai
->State
= HAL_SAI_STATE_READY
;
1289 /* Process Unlocked */
1297 hsai
->State
= HAL_SAI_STATE_READY
;
1299 /* Process Unlocked */
1311 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
1312 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1313 * the configuration information for SAI module.
1314 * @param pData Pointer to data buffer
1315 * @param Size Amount of data to be sent
1316 * @retval HAL status
1318 HAL_StatusTypeDef
HAL_SAI_Transmit_IT(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1320 if ((pData
== NULL
) || (Size
== 0U))
1325 if (hsai
->State
== HAL_SAI_STATE_READY
)
1327 /* Process Locked */
1330 hsai
->pBuffPtr
= pData
;
1331 hsai
->XferSize
= Size
;
1332 hsai
->XferCount
= Size
;
1333 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1334 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1336 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1338 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT8Bit
;
1340 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1342 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT16Bit
;
1346 hsai
->InterruptServiceRoutine
= SAI_Transmit_IT32Bit
;
1349 /* Fill the fifo before starting the communication */
1352 /* Enable FRQ and OVRUDR interrupts */
1353 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
1355 /* Check if the SAI is already enabled */
1356 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1358 /* Enable SAI peripheral */
1359 __HAL_SAI_ENABLE(hsai
);
1361 /* Process Unlocked */
1373 * @brief Receive an amount of data in non-blocking mode with Interrupt.
1374 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1375 * the configuration information for SAI module.
1376 * @param pData Pointer to data buffer
1377 * @param Size Amount of data to be received
1378 * @retval HAL status
1380 HAL_StatusTypeDef
HAL_SAI_Receive_IT(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1382 if ((pData
== NULL
) || (Size
== 0U))
1387 if (hsai
->State
== HAL_SAI_STATE_READY
)
1389 /* Process Locked */
1392 hsai
->pBuffPtr
= pData
;
1393 hsai
->XferSize
= Size
;
1394 hsai
->XferCount
= Size
;
1395 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1396 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1398 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
1400 hsai
->InterruptServiceRoutine
= SAI_Receive_IT8Bit
;
1402 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
1404 hsai
->InterruptServiceRoutine
= SAI_Receive_IT16Bit
;
1408 hsai
->InterruptServiceRoutine
= SAI_Receive_IT32Bit
;
1411 /* Enable TXE and OVRUDR interrupts */
1412 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
1414 /* Check if the SAI is already enabled */
1415 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1417 /* Enable SAI peripheral */
1418 __HAL_SAI_ENABLE(hsai
);
1421 /* Process Unlocked */
1433 * @brief Pause the audio stream playing from the Media.
1434 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1435 * the configuration information for SAI module.
1436 * @retval HAL status
1438 HAL_StatusTypeDef
HAL_SAI_DMAPause(SAI_HandleTypeDef
*hsai
)
1440 /* Process Locked */
1443 /* Pause the audio file playing by disabling the SAI DMA requests */
1444 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1446 /* Process Unlocked */
1453 * @brief Resume the audio stream playing from the Media.
1454 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1455 * the configuration information for SAI module.
1456 * @retval HAL status
1458 HAL_StatusTypeDef
HAL_SAI_DMAResume(SAI_HandleTypeDef
*hsai
)
1460 /* Process Locked */
1463 /* Enable the SAI DMA requests */
1464 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1466 /* If the SAI peripheral is still not enabled, enable it */
1467 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1469 /* Enable SAI peripheral */
1470 __HAL_SAI_ENABLE(hsai
);
1473 /* Process Unlocked */
1480 * @brief Stop the audio stream playing from the Media.
1481 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1482 * the configuration information for SAI module.
1483 * @retval HAL status
1485 HAL_StatusTypeDef
HAL_SAI_DMAStop(SAI_HandleTypeDef
*hsai
)
1487 HAL_StatusTypeDef status
= HAL_OK
;
1489 /* Process Locked */
1492 /* Disable the SAI DMA request */
1493 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1495 /* Abort the SAI Tx DMA Stream */
1496 if ((hsai
->State
== HAL_SAI_STATE_BUSY_TX
) && (hsai
->hdmatx
!= NULL
))
1498 if (HAL_DMA_Abort(hsai
->hdmatx
) != HAL_OK
)
1500 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1501 if (hsai
->hdmatx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1504 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1509 /* Abort the SAI Rx DMA Stream */
1510 if ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) && (hsai
->hdmarx
!= NULL
))
1512 if (HAL_DMA_Abort(hsai
->hdmarx
) != HAL_OK
)
1514 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1515 if (hsai
->hdmarx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1518 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1523 /* Disable SAI peripheral */
1524 if (SAI_Disable(hsai
) != HAL_OK
)
1529 /* Flush the fifo */
1530 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1532 /* Set hsai state to ready */
1533 hsai
->State
= HAL_SAI_STATE_READY
;
1535 /* Process Unlocked */
1542 * @brief Abort the current transfer and disable the SAI.
1543 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1544 * the configuration information for SAI module.
1545 * @retval HAL status
1547 HAL_StatusTypeDef
HAL_SAI_Abort(SAI_HandleTypeDef
*hsai
)
1549 HAL_StatusTypeDef status
= HAL_OK
;
1551 /* Process Locked */
1554 /* Check SAI DMA is enabled or not */
1555 if ((hsai
->Instance
->CR1
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
1557 /* Disable the SAI DMA request */
1558 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
1560 /* Abort the SAI Tx DMA Stream */
1561 if ((hsai
->State
== HAL_SAI_STATE_BUSY_TX
)&& (hsai
->hdmatx
!= NULL
))
1563 if (HAL_DMA_Abort(hsai
->hdmatx
) != HAL_OK
)
1565 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1566 if (hsai
->hdmatx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1569 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1574 /* Abort the SAI Rx DMA Stream */
1575 if ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) && (hsai
->hdmarx
!= NULL
))
1577 if (HAL_DMA_Abort(hsai
->hdmarx
) != HAL_OK
)
1579 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1580 if (hsai
->hdmarx
->ErrorCode
!= HAL_DMA_ERROR_NO_XFER
)
1583 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1589 /* Disabled All interrupt and clear all the flag */
1590 hsai
->Instance
->IMR
= 0;
1591 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
1593 /* Disable SAI peripheral */
1594 if (SAI_Disable(hsai
) != HAL_OK
)
1599 /* Flush the fifo */
1600 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
1602 /* Set hsai state to ready */
1603 hsai
->State
= HAL_SAI_STATE_READY
;
1605 /* Process Unlocked */
1612 * @brief Transmit an amount of data in non-blocking mode with DMA.
1613 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1614 * the configuration information for SAI module.
1615 * @param pData Pointer to data buffer
1616 * @param Size Amount of data to be sent
1617 * @retval HAL status
1619 HAL_StatusTypeDef
HAL_SAI_Transmit_DMA(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1621 uint32_t tickstart
= HAL_GetTick();
1623 if ((pData
== NULL
) || (Size
== 0U))
1628 if (hsai
->State
== HAL_SAI_STATE_READY
)
1630 /* Process Locked */
1633 hsai
->pBuffPtr
= pData
;
1634 hsai
->XferSize
= Size
;
1635 hsai
->XferCount
= Size
;
1636 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1637 hsai
->State
= HAL_SAI_STATE_BUSY_TX
;
1639 /* Set the SAI Tx DMA Half transfer complete callback */
1640 hsai
->hdmatx
->XferHalfCpltCallback
= SAI_DMATxHalfCplt
;
1642 /* Set the SAI TxDMA transfer complete callback */
1643 hsai
->hdmatx
->XferCpltCallback
= SAI_DMATxCplt
;
1645 /* Set the DMA error callback */
1646 hsai
->hdmatx
->XferErrorCallback
= SAI_DMAError
;
1648 /* Set the DMA Tx abort callback */
1649 hsai
->hdmatx
->XferAbortCallback
= NULL
;
1651 /* Enable the Tx DMA Stream */
1652 if (HAL_DMA_Start_IT(hsai
->hdmatx
, (uint32_t)hsai
->pBuffPtr
, (uint32_t)&hsai
->Instance
->DR
, hsai
->XferSize
) != HAL_OK
)
1658 /* Enable the interrupts for error handling */
1659 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
1661 /* Enable SAI Tx DMA Request */
1662 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1664 /* Wait untill FIFO is not empty */
1665 while ((hsai
->Instance
->SR
& SAI_xSR_FLVL
) == SAI_FIFOSTATUS_EMPTY
)
1667 /* Check for the Timeout */
1668 if ((HAL_GetTick() - tickstart
) > SAI_LONG_TIMEOUT
)
1670 /* Update error code */
1671 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
1673 /* Process Unlocked */
1680 /* Check if the SAI is already enabled */
1681 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1683 /* Enable SAI peripheral */
1684 __HAL_SAI_ENABLE(hsai
);
1687 /* Process Unlocked */
1699 * @brief Receive an amount of data in non-blocking mode with DMA.
1700 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1701 * the configuration information for SAI module.
1702 * @param pData Pointer to data buffer
1703 * @param Size Amount of data to be received
1704 * @retval HAL status
1706 HAL_StatusTypeDef
HAL_SAI_Receive_DMA(SAI_HandleTypeDef
*hsai
, uint8_t *pData
, uint16_t Size
)
1709 if ((pData
== NULL
) || (Size
== 0U))
1714 if (hsai
->State
== HAL_SAI_STATE_READY
)
1716 /* Process Locked */
1719 hsai
->pBuffPtr
= pData
;
1720 hsai
->XferSize
= Size
;
1721 hsai
->XferCount
= Size
;
1722 hsai
->ErrorCode
= HAL_SAI_ERROR_NONE
;
1723 hsai
->State
= HAL_SAI_STATE_BUSY_RX
;
1725 /* Set the SAI Rx DMA Half transfer complete callback */
1726 hsai
->hdmarx
->XferHalfCpltCallback
= SAI_DMARxHalfCplt
;
1728 /* Set the SAI Rx DMA transfer complete callback */
1729 hsai
->hdmarx
->XferCpltCallback
= SAI_DMARxCplt
;
1731 /* Set the DMA error callback */
1732 hsai
->hdmarx
->XferErrorCallback
= SAI_DMAError
;
1734 /* Set the DMA Rx abort callback */
1735 hsai
->hdmarx
->XferAbortCallback
= NULL
;
1737 /* Enable the Rx DMA Stream */
1738 if (HAL_DMA_Start_IT(hsai
->hdmarx
, (uint32_t)&hsai
->Instance
->DR
, (uint32_t)hsai
->pBuffPtr
, hsai
->XferSize
) != HAL_OK
)
1744 /* Enable the interrupts for error handling */
1745 __HAL_SAI_ENABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
1747 /* Enable SAI Rx DMA Request */
1748 hsai
->Instance
->CR1
|= SAI_xCR1_DMAEN
;
1750 /* Check if the SAI is already enabled */
1751 if ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) == 0U)
1753 /* Enable SAI peripheral */
1754 __HAL_SAI_ENABLE(hsai
);
1757 /* Process Unlocked */
1769 * @brief Enable the Tx mute mode.
1770 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1771 * the configuration information for SAI module.
1772 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1773 * @retval HAL status
1775 HAL_StatusTypeDef
HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef
*hsai
, uint16_t val
)
1777 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val
));
1779 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1781 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTEVAL
| SAI_xCR2_MUTE
);
1782 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTE
| (uint32_t)val
);
1789 * @brief Disable the Tx mute mode.
1790 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1791 * the configuration information for SAI module.
1792 * @retval HAL status
1794 HAL_StatusTypeDef
HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef
*hsai
)
1796 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1798 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTEVAL
| SAI_xCR2_MUTE
);
1805 * @brief Enable the Rx mute detection.
1806 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1807 * the configuration information for SAI module.
1808 * @param callback function called when the mute is detected.
1809 * @param counter number a data before mute detection max 63.
1810 * @retval HAL status
1812 HAL_StatusTypeDef
HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef
*hsai
, SAIcallback callback
, uint16_t counter
)
1814 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter
));
1816 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1818 /* set the mute counter */
1819 CLEAR_BIT(hsai
->Instance
->CR2
, SAI_xCR2_MUTECNT
);
1820 SET_BIT(hsai
->Instance
->CR2
, (uint32_t)((uint32_t)counter
<< SAI_xCR2_MUTECNT_Pos
));
1821 hsai
->mutecallback
= callback
;
1822 /* enable the IT interrupt */
1823 __HAL_SAI_ENABLE_IT(hsai
, SAI_IT_MUTEDET
);
1830 * @brief Disable the Rx mute detection.
1831 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1832 * the configuration information for SAI module.
1833 * @retval HAL status
1835 HAL_StatusTypeDef
HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef
*hsai
)
1837 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1839 /* set the mutecallback to NULL */
1840 hsai
->mutecallback
= NULL
;
1841 /* enable the IT interrupt */
1842 __HAL_SAI_DISABLE_IT(hsai
, SAI_IT_MUTEDET
);
1849 * @brief Handle SAI interrupt request.
1850 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1851 * the configuration information for SAI module.
1854 void HAL_SAI_IRQHandler(SAI_HandleTypeDef
*hsai
)
1856 if (hsai
->State
!= HAL_SAI_STATE_RESET
)
1858 uint32_t itflags
= hsai
->Instance
->SR
;
1859 uint32_t itsources
= hsai
->Instance
->IMR
;
1860 uint32_t cr1config
= hsai
->Instance
->CR1
;
1863 /* SAI Fifo request interrupt occured ------------------------------------*/
1864 if (((itflags
& SAI_xSR_FREQ
) == SAI_xSR_FREQ
) && ((itsources
& SAI_IT_FREQ
) == SAI_IT_FREQ
))
1866 hsai
->InterruptServiceRoutine(hsai
);
1868 /* SAI Overrun error interrupt occurred ----------------------------------*/
1869 else if (((itflags
& SAI_FLAG_OVRUDR
) == SAI_FLAG_OVRUDR
) && ((itsources
& SAI_IT_OVRUDR
) == SAI_IT_OVRUDR
))
1871 /* Clear the SAI Overrun flag */
1872 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
1873 /* Get the SAI error code */
1874 tmperror
= ((hsai
->State
== HAL_SAI_STATE_BUSY_RX
) ? HAL_SAI_ERROR_OVR
: HAL_SAI_ERROR_UDR
);
1875 /* Change the SAI error code */
1876 hsai
->ErrorCode
|= tmperror
;
1877 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1878 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1879 hsai
->ErrorCallback(hsai
);
1881 HAL_SAI_ErrorCallback(hsai
);
1884 /* SAI mutedet interrupt occurred ----------------------------------*/
1885 else if (((itflags
& SAI_FLAG_MUTEDET
) == SAI_FLAG_MUTEDET
) && ((itsources
& SAI_IT_MUTEDET
) == SAI_IT_MUTEDET
))
1887 /* Clear the SAI mutedet flag */
1888 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_MUTEDET
);
1889 /* call the call back function */
1890 if (hsai
->mutecallback
!= NULL
)
1892 /* inform the user that an RX mute event has been detected */
1893 hsai
->mutecallback();
1896 /* SAI AFSDET interrupt occurred ----------------------------------*/
1897 else if (((itflags
& SAI_FLAG_AFSDET
) == SAI_FLAG_AFSDET
) && ((itsources
& SAI_IT_AFSDET
) == SAI_IT_AFSDET
))
1899 /* Clear the SAI AFSDET flag */
1900 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_AFSDET
);
1902 /* Change the SAI error code */
1903 hsai
->ErrorCode
|= HAL_SAI_ERROR_AFSDET
;
1905 /* Check SAI DMA is enabled or not */
1906 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
1908 /* Abort the SAI DMA Streams */
1909 if (hsai
->hdmatx
!= NULL
)
1911 /* Set the DMA Tx abort callback */
1912 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
1914 /* Abort DMA in IT mode */
1915 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
1917 /* Update SAI error code */
1918 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1920 /* Call SAI error callback */
1921 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1922 hsai
->ErrorCallback(hsai
);
1924 HAL_SAI_ErrorCallback(hsai
);
1928 if (hsai
->hdmarx
!= NULL
)
1930 /* Set the DMA Rx abort callback */
1931 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
1933 /* Abort DMA in IT mode */
1934 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
1936 /* Update SAI error code */
1937 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1939 /* Call SAI error callback */
1940 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1941 hsai
->ErrorCallback(hsai
);
1943 HAL_SAI_ErrorCallback(hsai
);
1951 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
1952 (void) HAL_SAI_Abort(hsai
);
1954 /* Set error callback */
1955 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1956 hsai
->ErrorCallback(hsai
);
1958 HAL_SAI_ErrorCallback(hsai
);
1962 /* SAI LFSDET interrupt occurred ----------------------------------*/
1963 else if (((itflags
& SAI_FLAG_LFSDET
) == SAI_FLAG_LFSDET
) && ((itsources
& SAI_IT_LFSDET
) == SAI_IT_LFSDET
))
1965 /* Clear the SAI LFSDET flag */
1966 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_LFSDET
);
1968 /* Change the SAI error code */
1969 hsai
->ErrorCode
|= HAL_SAI_ERROR_LFSDET
;
1971 /* Check SAI DMA is enabled or not */
1972 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
1974 /* Abort the SAI DMA Streams */
1975 if (hsai
->hdmatx
!= NULL
)
1977 /* Set the DMA Tx abort callback */
1978 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
1980 /* Abort DMA in IT mode */
1981 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
1983 /* Update SAI error code */
1984 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
1986 /* Call SAI error callback */
1987 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
1988 hsai
->ErrorCallback(hsai
);
1990 HAL_SAI_ErrorCallback(hsai
);
1994 if (hsai
->hdmarx
!= NULL
)
1996 /* Set the DMA Rx abort callback */
1997 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
1999 /* Abort DMA in IT mode */
2000 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
2002 /* Update SAI error code */
2003 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2005 /* Call SAI error callback */
2006 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2007 hsai
->ErrorCallback(hsai
);
2009 HAL_SAI_ErrorCallback(hsai
);
2017 /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
2018 (void) HAL_SAI_Abort(hsai
);
2020 /* Set error callback */
2021 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2022 hsai
->ErrorCallback(hsai
);
2024 HAL_SAI_ErrorCallback(hsai
);
2028 /* SAI WCKCFG interrupt occurred ----------------------------------*/
2029 else if (((itflags
& SAI_FLAG_WCKCFG
) == SAI_FLAG_WCKCFG
) && ((itsources
& SAI_IT_WCKCFG
) == SAI_IT_WCKCFG
))
2031 /* Clear the SAI WCKCFG flag */
2032 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_WCKCFG
);
2034 /* Change the SAI error code */
2035 hsai
->ErrorCode
|= HAL_SAI_ERROR_WCKCFG
;
2037 /* Check SAI DMA is enabled or not */
2038 if ((cr1config
& SAI_xCR1_DMAEN
) == SAI_xCR1_DMAEN
)
2040 /* Abort the SAI DMA Streams */
2041 if (hsai
->hdmatx
!= NULL
)
2043 /* Set the DMA Tx abort callback */
2044 hsai
->hdmatx
->XferAbortCallback
= SAI_DMAAbort
;
2046 /* Abort DMA in IT mode */
2047 if (HAL_DMA_Abort_IT(hsai
->hdmatx
) != HAL_OK
)
2049 /* Update SAI error code */
2050 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2052 /* Call SAI error callback */
2053 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2054 hsai
->ErrorCallback(hsai
);
2056 HAL_SAI_ErrorCallback(hsai
);
2060 if (hsai
->hdmarx
!= NULL
)
2062 /* Set the DMA Rx abort callback */
2063 hsai
->hdmarx
->XferAbortCallback
= SAI_DMAAbort
;
2065 /* Abort DMA in IT mode */
2066 if (HAL_DMA_Abort_IT(hsai
->hdmarx
) != HAL_OK
)
2068 /* Update SAI error code */
2069 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2071 /* Call SAI error callback */
2072 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2073 hsai
->ErrorCallback(hsai
);
2075 HAL_SAI_ErrorCallback(hsai
);
2082 /* If WCKCFG occurs, SAI audio block is automatically disabled */
2083 /* Disable all interrupts and clear all flags */
2084 hsai
->Instance
->IMR
= 0U;
2085 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
2086 /* Set the SAI state to ready to be able to start again the process */
2087 hsai
->State
= HAL_SAI_STATE_READY
;
2089 /* Initialize XferCount */
2090 hsai
->XferCount
= 0U;
2092 /* SAI error Callback */
2093 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2094 hsai
->ErrorCallback(hsai
);
2096 HAL_SAI_ErrorCallback(hsai
);
2100 /* SAI CNRDY interrupt occurred ----------------------------------*/
2101 else if (((itflags
& SAI_FLAG_CNRDY
) == SAI_FLAG_CNRDY
) && ((itsources
& SAI_IT_CNRDY
) == SAI_IT_CNRDY
))
2103 /* Clear the SAI CNRDY flag */
2104 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_CNRDY
);
2105 /* Change the SAI error code */
2106 hsai
->ErrorCode
|= HAL_SAI_ERROR_CNREADY
;
2107 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
2108 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2109 hsai
->ErrorCallback(hsai
);
2111 HAL_SAI_ErrorCallback(hsai
);
2122 * @brief Tx Transfer completed callback.
2123 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2124 * the configuration information for SAI module.
2127 __weak
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef
*hsai
)
2129 /* Prevent unused argument(s) compilation warning */
2132 /* NOTE : This function should not be modified, when the callback is needed,
2133 the HAL_SAI_TxCpltCallback could be implemented in the user file
2138 * @brief Tx Transfer Half completed callback.
2139 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2140 * the configuration information for SAI module.
2143 __weak
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef
*hsai
)
2145 /* Prevent unused argument(s) compilation warning */
2148 /* NOTE : This function should not be modified, when the callback is needed,
2149 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
2154 * @brief Rx Transfer completed callback.
2155 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2156 * the configuration information for SAI module.
2159 __weak
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef
*hsai
)
2161 /* Prevent unused argument(s) compilation warning */
2164 /* NOTE : This function should not be modified, when the callback is needed,
2165 the HAL_SAI_RxCpltCallback could be implemented in the user file
2170 * @brief Rx Transfer half completed callback.
2171 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2172 * the configuration information for SAI module.
2175 __weak
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef
*hsai
)
2177 /* Prevent unused argument(s) compilation warning */
2180 /* NOTE : This function should not be modified, when the callback is needed,
2181 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
2186 * @brief SAI error callback.
2187 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2188 * the configuration information for SAI module.
2191 __weak
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef
*hsai
)
2193 /* Prevent unused argument(s) compilation warning */
2196 /* NOTE : This function should not be modified, when the callback is needed,
2197 the HAL_SAI_ErrorCallback could be implemented in the user file
2205 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
2206 * @brief Peripheral State functions
2209 ===============================================================================
2210 ##### Peripheral State and Errors functions #####
2211 ===============================================================================
2213 This subsection permits to get in run-time the status of the peripheral
2221 * @brief Return the SAI handle state.
2222 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2223 * the configuration information for SAI module.
2226 HAL_SAI_StateTypeDef
HAL_SAI_GetState(SAI_HandleTypeDef
*hsai
)
2232 * @brief Return the SAI error code.
2233 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2234 * the configuration information for the specified SAI Block.
2235 * @retval SAI Error Code
2237 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef
*hsai
)
2239 return hsai
->ErrorCode
;
2250 /** @addtogroup SAI_Private_Functions
2251 * @brief Private functions
2256 * @brief Initialize the SAI I2S protocol according to the specified parameters
2257 * in the SAI_InitTypeDef and create the associated handle.
2258 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2259 * the configuration information for SAI module.
2260 * @param protocol one of the supported protocol.
2261 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
2262 * @param nbslot number of slot minimum value is 2 and max is 16.
2263 * the value must be a multiple of 2.
2264 * @retval HAL status
2266 static HAL_StatusTypeDef
SAI_InitI2S(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
2268 HAL_StatusTypeDef status
= HAL_OK
;
2270 hsai
->Init
.Protocol
= SAI_FREE_PROTOCOL
;
2271 hsai
->Init
.FirstBit
= SAI_FIRSTBIT_MSB
;
2272 /* Compute ClockStrobing according AudioMode */
2273 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2276 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_FALLINGEDGE
;
2281 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_RISINGEDGE
;
2283 hsai
->FrameInit
.FSDefinition
= SAI_FS_CHANNEL_IDENTIFICATION
;
2284 hsai
->SlotInit
.SlotActive
= SAI_SLOTACTIVE_ALL
;
2285 hsai
->SlotInit
.FirstBitOffset
= 0;
2286 hsai
->SlotInit
.SlotNumber
= nbslot
;
2288 /* in IS2 the number of slot must be even */
2289 if ((nbslot
& 0x1U
) != 0U)
2294 if (protocol
== SAI_I2S_STANDARD
)
2296 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_LOW
;
2297 hsai
->FrameInit
.FSOffset
= SAI_FS_BEFOREFIRSTBIT
;
2301 /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
2302 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_HIGH
;
2303 hsai
->FrameInit
.FSOffset
= SAI_FS_FIRSTBIT
;
2306 /* Frame definition */
2309 case SAI_PROTOCOL_DATASIZE_16BIT
:
2310 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2311 hsai
->FrameInit
.FrameLength
= 32U * (nbslot
/ 2U);
2312 hsai
->FrameInit
.ActiveFrameLength
= 16U * (nbslot
/ 2U);
2313 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_16B
;
2315 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED
:
2316 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2317 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2318 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2319 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2321 case SAI_PROTOCOL_DATASIZE_24BIT
:
2322 hsai
->Init
.DataSize
= SAI_DATASIZE_24
;
2323 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2324 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2325 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2327 case SAI_PROTOCOL_DATASIZE_32BIT
:
2328 hsai
->Init
.DataSize
= SAI_DATASIZE_32
;
2329 hsai
->FrameInit
.FrameLength
= 64U * (nbslot
/ 2U);
2330 hsai
->FrameInit
.ActiveFrameLength
= 32U * (nbslot
/ 2U);
2331 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2337 if (protocol
== SAI_I2S_LSBJUSTIFIED
)
2339 if (datasize
== SAI_PROTOCOL_DATASIZE_16BITEXTENDED
)
2341 hsai
->SlotInit
.FirstBitOffset
= 16;
2343 if (datasize
== SAI_PROTOCOL_DATASIZE_24BIT
)
2345 hsai
->SlotInit
.FirstBitOffset
= 8;
2352 * @brief Initialize the SAI PCM protocol according to the specified parameters
2353 * in the SAI_InitTypeDef and create the associated handle.
2354 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2355 * the configuration information for SAI module.
2356 * @param protocol one of the supported protocol
2357 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
2358 * @param nbslot number of slot minimum value is 1 and the max is 16.
2359 * @retval HAL status
2361 static HAL_StatusTypeDef
SAI_InitPCM(SAI_HandleTypeDef
*hsai
, uint32_t protocol
, uint32_t datasize
, uint32_t nbslot
)
2363 HAL_StatusTypeDef status
= HAL_OK
;
2365 hsai
->Init
.Protocol
= SAI_FREE_PROTOCOL
;
2366 hsai
->Init
.FirstBit
= SAI_FIRSTBIT_MSB
;
2367 /* Compute ClockStrobing according AudioMode */
2368 if ((hsai
->Init
.AudioMode
== SAI_MODEMASTER_TX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2371 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_RISINGEDGE
;
2376 hsai
->Init
.ClockStrobing
= SAI_CLOCKSTROBING_FALLINGEDGE
;
2378 hsai
->FrameInit
.FSDefinition
= SAI_FS_STARTFRAME
;
2379 hsai
->FrameInit
.FSPolarity
= SAI_FS_ACTIVE_HIGH
;
2380 hsai
->FrameInit
.FSOffset
= SAI_FS_BEFOREFIRSTBIT
;
2381 hsai
->SlotInit
.FirstBitOffset
= 0;
2382 hsai
->SlotInit
.SlotNumber
= nbslot
;
2383 hsai
->SlotInit
.SlotActive
= SAI_SLOTACTIVE_ALL
;
2385 if (protocol
== SAI_PCM_SHORT
)
2387 hsai
->FrameInit
.ActiveFrameLength
= 1;
2392 hsai
->FrameInit
.ActiveFrameLength
= 13;
2397 case SAI_PROTOCOL_DATASIZE_16BIT
:
2398 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2399 hsai
->FrameInit
.FrameLength
= 16U * nbslot
;
2400 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_16B
;
2402 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED
:
2403 hsai
->Init
.DataSize
= SAI_DATASIZE_16
;
2404 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2405 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2407 case SAI_PROTOCOL_DATASIZE_24BIT
:
2408 hsai
->Init
.DataSize
= SAI_DATASIZE_24
;
2409 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2410 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2412 case SAI_PROTOCOL_DATASIZE_32BIT
:
2413 hsai
->Init
.DataSize
= SAI_DATASIZE_32
;
2414 hsai
->FrameInit
.FrameLength
= 32U * nbslot
;
2415 hsai
->SlotInit
.SlotSize
= SAI_SLOTSIZE_32B
;
2426 * @brief Fill the fifo.
2427 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2428 * the configuration information for SAI module.
2431 static void SAI_FillFifo(SAI_HandleTypeDef
*hsai
)
2435 /* fill the fifo with data before to enabled the SAI */
2436 while (((hsai
->Instance
->SR
& SAI_xSR_FLVL
) != SAI_FIFOSTATUS_FULL
) && (hsai
->XferCount
> 0U))
2438 if ((hsai
->Init
.DataSize
== SAI_DATASIZE_8
) && (hsai
->Init
.CompandingMode
== SAI_NOCOMPANDING
))
2440 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
2443 else if (hsai
->Init
.DataSize
<= SAI_DATASIZE_16
)
2445 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2447 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2449 hsai
->Instance
->DR
= temp
;
2453 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2455 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2457 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
2459 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
2461 hsai
->Instance
->DR
= temp
;
2468 * @brief Return the interrupt flag to set according the SAI setup.
2469 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2470 * the configuration information for SAI module.
2471 * @param mode SAI_MODE_DMA or SAI_MODE_IT
2472 * @retval the list of the IT flag to enable
2474 static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef
*hsai
, SAI_ModeTypedef mode
)
2476 uint32_t tmpIT
= SAI_IT_OVRUDR
;
2478 if (mode
== SAI_MODE_IT
)
2480 tmpIT
|= SAI_IT_FREQ
;
2483 if ((hsai
->Init
.Protocol
== SAI_AC97_PROTOCOL
) &&
2484 ((hsai
->Init
.AudioMode
== SAI_MODESLAVE_RX
) || (hsai
->Init
.AudioMode
== SAI_MODEMASTER_RX
)))
2486 tmpIT
|= SAI_IT_CNRDY
;
2489 if ((hsai
->Init
.AudioMode
== SAI_MODESLAVE_RX
) || (hsai
->Init
.AudioMode
== SAI_MODESLAVE_TX
))
2491 tmpIT
|= SAI_IT_AFSDET
| SAI_IT_LFSDET
;
2495 /* hsai has been configured in master mode */
2496 tmpIT
|= SAI_IT_WCKCFG
;
2502 * @brief Disable the SAI and wait for the disabling.
2503 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2504 * the configuration information for SAI module.
2507 static HAL_StatusTypeDef
SAI_Disable(SAI_HandleTypeDef
*hsai
)
2509 register uint32_t count
= SAI_DEFAULT_TIMEOUT
* (SystemCoreClock
/ 7U / 1000U);
2510 HAL_StatusTypeDef status
= HAL_OK
;
2512 /* Disable the SAI instance */
2513 __HAL_SAI_DISABLE(hsai
);
2517 /* Check for the Timeout */
2520 /* Update error code */
2521 hsai
->ErrorCode
|= HAL_SAI_ERROR_TIMEOUT
;
2522 status
= HAL_TIMEOUT
;
2527 while ((hsai
->Instance
->CR1
& SAI_xCR1_SAIEN
) != 0U);
2533 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
2534 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2535 * the configuration information for SAI module.
2538 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef
*hsai
)
2540 if (hsai
->XferCount
== 0U)
2542 /* Handle the end of the transmission */
2543 /* Disable FREQ and OVRUDR interrupts */
2544 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2545 hsai
->State
= HAL_SAI_STATE_READY
;
2546 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2547 hsai
->TxCpltCallback(hsai
);
2549 HAL_SAI_TxCpltCallback(hsai
);
2554 /* Write data on DR register */
2555 hsai
->Instance
->DR
= *hsai
->pBuffPtr
;
2562 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
2563 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2564 * the configuration information for SAI module.
2567 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef
*hsai
)
2569 if (hsai
->XferCount
== 0U)
2571 /* Handle the end of the transmission */
2572 /* Disable FREQ and OVRUDR interrupts */
2573 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2574 hsai
->State
= HAL_SAI_STATE_READY
;
2575 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2576 hsai
->TxCpltCallback(hsai
);
2578 HAL_SAI_TxCpltCallback(hsai
);
2583 /* Write data on DR register */
2585 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2587 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2589 hsai
->Instance
->DR
= temp
;
2595 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
2596 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2597 * the configuration information for SAI module.
2600 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef
*hsai
)
2602 if (hsai
->XferCount
== 0U)
2604 /* Handle the end of the transmission */
2605 /* Disable FREQ and OVRUDR interrupts */
2606 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2607 hsai
->State
= HAL_SAI_STATE_READY
;
2608 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2609 hsai
->TxCpltCallback(hsai
);
2611 HAL_SAI_TxCpltCallback(hsai
);
2616 /* Write data on DR register */
2618 temp
= (uint32_t)(*hsai
->pBuffPtr
);
2620 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 8);
2622 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 16);
2624 temp
|= ((uint32_t)(*hsai
->pBuffPtr
) << 24);
2626 hsai
->Instance
->DR
= temp
;
2632 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
2633 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2634 * the configuration information for SAI module.
2637 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef
*hsai
)
2640 *hsai
->pBuffPtr
= (uint8_t)hsai
->Instance
->DR
;
2644 /* Check end of the transfer */
2645 if (hsai
->XferCount
== 0U)
2647 /* Disable TXE and OVRUDR interrupts */
2648 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2650 /* Clear the SAI Overrun flag */
2651 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2653 hsai
->State
= HAL_SAI_STATE_READY
;
2654 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2655 hsai
->RxCpltCallback(hsai
);
2657 HAL_SAI_RxCpltCallback(hsai
);
2663 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2664 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2665 * the configuration information for SAI module.
2668 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef
*hsai
)
2673 temp
= hsai
->Instance
->DR
;
2674 *hsai
->pBuffPtr
= (uint8_t)temp
;
2676 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
2680 /* Check end of the transfer */
2681 if (hsai
->XferCount
== 0U)
2683 /* Disable TXE and OVRUDR interrupts */
2684 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2686 /* Clear the SAI Overrun flag */
2687 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2689 hsai
->State
= HAL_SAI_STATE_READY
;
2690 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2691 hsai
->RxCpltCallback(hsai
);
2693 HAL_SAI_RxCpltCallback(hsai
);
2699 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2700 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2701 * the configuration information for SAI module.
2704 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef
*hsai
)
2709 temp
= hsai
->Instance
->DR
;
2710 *hsai
->pBuffPtr
= (uint8_t)temp
;
2712 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 8);
2714 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 16);
2716 *hsai
->pBuffPtr
= (uint8_t)(temp
>> 24);
2720 /* Check end of the transfer */
2721 if (hsai
->XferCount
== 0U)
2723 /* Disable TXE and OVRUDR interrupts */
2724 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_IT
));
2726 /* Clear the SAI Overrun flag */
2727 __HAL_SAI_CLEAR_FLAG(hsai
, SAI_FLAG_OVRUDR
);
2729 hsai
->State
= HAL_SAI_STATE_READY
;
2730 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2731 hsai
->RxCpltCallback(hsai
);
2733 HAL_SAI_RxCpltCallback(hsai
);
2739 * @brief DMA SAI transmit process complete callback.
2740 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2741 * the configuration information for the specified DMA module.
2744 static void SAI_DMATxCplt(DMA_HandleTypeDef
*hdma
)
2746 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2748 if (hdma
->Init
.Mode
!= DMA_CIRCULAR
)
2750 hsai
->XferCount
= 0;
2752 /* Disable SAI Tx DMA Request */
2753 hsai
->Instance
->CR1
&= (uint32_t)(~SAI_xCR1_DMAEN
);
2755 /* Stop the interrupts error handling */
2756 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
2758 hsai
->State
= HAL_SAI_STATE_READY
;
2760 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2761 hsai
->TxCpltCallback(hsai
);
2763 HAL_SAI_TxCpltCallback(hsai
);
2768 * @brief DMA SAI transmit process half complete callback.
2769 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2770 * the configuration information for the specified DMA module.
2773 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef
*hdma
)
2775 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2777 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2778 hsai
->TxHalfCpltCallback(hsai
);
2780 HAL_SAI_TxHalfCpltCallback(hsai
);
2785 * @brief DMA SAI receive process complete callback.
2786 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2787 * the configuration information for the specified DMA module.
2790 static void SAI_DMARxCplt(DMA_HandleTypeDef
*hdma
)
2792 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2794 if (hdma
->Init
.Mode
!= DMA_CIRCULAR
)
2796 /* Disable Rx DMA Request */
2797 hsai
->Instance
->CR1
&= (uint32_t)(~SAI_xCR1_DMAEN
);
2798 hsai
->XferCount
= 0;
2800 /* Stop the interrupts error handling */
2801 __HAL_SAI_DISABLE_IT(hsai
, SAI_InterruptFlag(hsai
, SAI_MODE_DMA
));
2803 hsai
->State
= HAL_SAI_STATE_READY
;
2805 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2806 hsai
->RxCpltCallback(hsai
);
2808 HAL_SAI_RxCpltCallback(hsai
);
2813 * @brief DMA SAI receive process half complete callback
2814 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2815 * the configuration information for the specified DMA module.
2818 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef
*hdma
)
2820 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2822 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2823 hsai
->RxHalfCpltCallback(hsai
);
2825 HAL_SAI_RxHalfCpltCallback(hsai
);
2830 * @brief DMA SAI communication error callback.
2831 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2832 * the configuration information for the specified DMA module.
2835 static void SAI_DMAError(DMA_HandleTypeDef
*hdma
)
2837 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2839 /* Ignore DMA FIFO error */
2840 if (HAL_DMA_GetError(hdma
) != HAL_DMA_ERROR_FE
)
2842 /* Set SAI error code */
2843 hsai
->ErrorCode
|= HAL_SAI_ERROR_DMA
;
2845 /* Disable the SAI DMA request */
2846 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
2848 /* Disable SAI peripheral */
2849 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2850 (void) SAI_Disable(hsai
);
2852 /* Set the SAI state ready to be able to start again the process */
2853 hsai
->State
= HAL_SAI_STATE_READY
;
2855 /* Initialize XferCount */
2856 hsai
->XferCount
= 0U;
2858 /* SAI error Callback */
2859 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2860 hsai
->ErrorCallback(hsai
);
2862 HAL_SAI_ErrorCallback(hsai
);
2868 * @brief DMA SAI Abort callback.
2869 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2870 * the configuration information for the specified DMA module.
2873 static void SAI_DMAAbort(DMA_HandleTypeDef
*hdma
)
2875 SAI_HandleTypeDef
*hsai
= (SAI_HandleTypeDef
*)((DMA_HandleTypeDef
*)hdma
)->Parent
;
2877 /* Disable DMA request */
2878 hsai
->Instance
->CR1
&= ~SAI_xCR1_DMAEN
;
2880 /* Disable all interrupts and clear all flags */
2881 hsai
->Instance
->IMR
= 0U;
2882 hsai
->Instance
->CLRFR
= 0xFFFFFFFFU
;
2884 if (hsai
->ErrorCode
!= HAL_SAI_ERROR_WCKCFG
)
2886 /* Disable SAI peripheral */
2887 /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
2888 (void) SAI_Disable(hsai
);
2890 /* Flush the fifo */
2891 SET_BIT(hsai
->Instance
->CR2
, SAI_xCR2_FFLUSH
);
2893 /* Set the SAI state to ready to be able to start again the process */
2894 hsai
->State
= HAL_SAI_STATE_READY
;
2896 /* Initialize XferCount */
2897 hsai
->XferCount
= 0U;
2899 /* SAI error Callback */
2900 #if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
2901 hsai
->ErrorCallback(hsai
);
2903 HAL_SAI_ErrorCallback(hsai
);
2911 #endif /* HAL_SAI_MODULE_ENABLED */
2920 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/