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