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