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