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