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