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