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