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