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