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