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