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