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