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