comparison Common/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c @ 160:e3ca52b8e7fa

Merge with FlipDisplay
author heinrichsweikamp
date Thu, 07 Mar 2019 15:06:43 +0100
parents c78bcbd5deda
children
comparison
equal deleted inserted replaced
80:cc2bb7bb8456 160:e3ca52b8e7fa
1 /**
2 ******************************************************************************
3 * @file stm32f4xx_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 [..]
52 (@) SAI Clock Source configuration is managed differently depending on the selected
53 STM32F4 devices :
54 (+@) For STM32F446xx devices, the configuration is managed through RCCEx_PeriphCLKConfig()
55 function in the HAL RCC drivers
56 (+@) For STM32F439xx/STM32F437xx/STM32F429xx/STM32F427xx devices, the configuration
57 is managed within HAL SAI drivers through HAL_SAI_Init() function using
58 ClockSource field of SAI_InitTypeDef structure.
59 [..]
60 (@) Make sure that either:
61 (+@) I2S PLL is configured or
62 (+@) SAI PLL is configured or
63 (+@) External clock source is configured after setting correctly
64 the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file.
65 [..]
66 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
67 for the external slaves even if there is no data in the FIFO, However FS signal
68 generation is conditioned by the presence of data in the FIFO.
69
70 [..]
71 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
72 and FS signal for the external slaves.
73
74 [..]
75 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
76 (+@) First bit Offset <= (SLOT size - Data size)
77 (+@) Data size <= SLOT size
78 (+@) Number of SLOT x SLOT size = Frame length
79 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
80
81 [..]
82 Three operation modes are available within this driver :
83
84 *** Polling mode IO operation ***
85 =================================
86 [..]
87 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
88 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
89
90 *** Interrupt mode IO operation ***
91 ===================================
92 [..]
93 (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
94 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
95 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
96 (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
97 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
98 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
99 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
100 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
101
102 *** DMA mode IO operation ***
103 =============================
104 [..]
105 (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
106 (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
107 add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
108 (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
109 (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
110 add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
111 (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
112 add his own code by customization of function pointer HAL_SAI_ErrorCallback()
113 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
114 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
115 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
116
117 *** SAI HAL driver additional function list ***
118 ===============================================
119 [..]
120 Below the list the others API available SAI HAL driver :
121
122 (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
123 (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
124 (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
125 (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
126 (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
127 (+) HAL_SAI_Abort(): Abort the current transfer
128
129 *** SAI HAL driver macros list ***
130 ==================================
131 [..]
132 Below the list of most used macros in SAI HAL driver :
133
134 (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
135 (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
136 (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
137 (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
138 (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
139 enabled or disabled
140 (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
141
142 @endverbatim
143 ******************************************************************************
144 * @attention
145 *
146 * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
147 *
148 * Redistribution and use in source and binary forms, with or without modification,
149 * are permitted provided that the following conditions are met:
150 * 1. Redistributions of source code must retain the above copyright notice,
151 * this list of conditions and the following disclaimer.
152 * 2. Redistributions in binary form must reproduce the above copyright notice,
153 * this list of conditions and the following disclaimer in the documentation
154 * and/or other materials provided with the distribution.
155 * 3. Neither the name of STMicroelectronics nor the names of its contributors
156 * may be used to endorse or promote products derived from this software
157 * without specific prior written permission.
158 *
159 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
160 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
162 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
163 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
164 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
165 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
166 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
167 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
168 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
169 *
170 ******************************************************************************
171 */
172
173 /* Includes ------------------------------------------------------------------*/
174 #include "stm32f4xx_hal.h"
175
176 /** @addtogroup STM32F4xx_HAL_Driver
177 * @{
178 */
179
180 /** @defgroup SAI SAI
181 * @brief SAI HAL module driver
182 * @{
183 */
184
185 #ifdef HAL_SAI_MODULE_ENABLED
186
187 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
188 defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\
189 defined(STM32F423xx)
190
191 /** @defgroup SAI_Private_Typedefs SAI Private Typedefs
192 * @{
193 */
194 typedef enum {
195 SAI_MODE_DMA,
196 SAI_MODE_IT
197 }SAI_ModeTypedef;
198 /**
199 * @}
200 */
201
202 /* Private define ------------------------------------------------------------*/
203
204 /** @defgroup SAI_Private_Constants SAI Private Constants
205 * @{
206 */
207 #define SAI_FIFO_SIZE 8U
208 #define SAI_DEFAULT_TIMEOUT 4U /* 4ms */
209 /**
210 * @}
211 */
212
213 /* Private macro -------------------------------------------------------------*/
214 /* Private variables ---------------------------------------------------------*/
215 /* Private function prototypes -----------------------------------------------*/
216
217 /** @defgroup SAI_Private_Functions SAI Private Functions
218 * @{
219 */
220 static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
221 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode);
222 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
223 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
224
225 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
226 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
227 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
228 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
229 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
230 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
231 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
232
233 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
234 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
235 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
236 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
237 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
238 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
239 /**
240 * @}
241 */
242
243 /* Exported functions ---------------------------------------------------------*/
244
245 /** @defgroup SAI_Exported_Functions SAI Exported Functions
246 * @{
247 */
248
249 /** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions
250 * @brief Initialization and Configuration functions
251 *
252 @verbatim
253 ===============================================================================
254 ##### Initialization and de-initialization functions #####
255 ===============================================================================
256 [..] This subsection provides a set of functions allowing to initialize and
257 de-initialize the SAIx peripheral:
258
259 (+) User must implement HAL_SAI_MspInit() function in which he configures
260 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
261
262 (+) Call the function HAL_SAI_Init() to configure the selected device with
263 the selected configuration:
264 (++) Mode (Master/slave TX/RX)
265 (++) Protocol
266 (++) Data Size
267 (++) MCLK Output
268 (++) Audio frequency
269 (++) FIFO Threshold
270 (++) Frame Config
271 (++) Slot Config
272
273 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
274 of the selected SAI peripheral.
275
276 @endverbatim
277 * @{
278 */
279
280 /**
281 * @brief Initialize the structure FrameInit, SlotInit and the low part of
282 * Init according to the specified parameters and call the function
283 * HAL_SAI_Init to initialize the SAI block.
284 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
285 * the configuration information for SAI module.
286 * @param protocol one of the supported protocol @ref SAI_Protocol
287 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
288 * the configuration information for SAI module.
289 * @param nbslot Number of slot.
290 * @retval HAL status
291 */
292 HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
293 {
294 HAL_StatusTypeDef status = HAL_OK;
295
296 /* Check the parameters */
297 assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
298 assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
299
300 switch(protocol)
301 {
302 case SAI_I2S_STANDARD :
303 case SAI_I2S_MSBJUSTIFIED :
304 case SAI_I2S_LSBJUSTIFIED :
305 status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
306 break;
307 case SAI_PCM_LONG :
308 case SAI_PCM_SHORT :
309 status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
310 break;
311 default :
312 status = HAL_ERROR;
313 break;
314 }
315
316 if(status == HAL_OK)
317 {
318 status = HAL_SAI_Init(hsai);
319 }
320
321 return status;
322 }
323
324 /**
325 * @brief Initialize the SAI according to the specified parameters.
326 * in the SAI_InitTypeDef structure and initialize the associated handle.
327 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
328 * the configuration information for SAI module.
329 * @retval HAL status
330 */
331 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
332 {
333 uint32_t tmpregisterGCR = 0U;
334
335 /* This variable used to store the SAI_CK_x (value in Hz) */
336 uint32_t freq = 0U;
337
338 /* This variable is used to compute CKSTR bits of SAI CR1 according to
339 ClockStrobing and AudioMode fields */
340 uint32_t ckstr_bits = 0U;
341 uint32_t syncen_bits = 0U;
342
343 /* Check the SAI handle allocation */
344 if(hsai == NULL)
345 {
346 return HAL_ERROR;
347 }
348
349 /* check the instance */
350 assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
351
352 /* Check the SAI Block parameters */
353 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
354 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
355 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
356 assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
357 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
358 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
359 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
360 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
361 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
362 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
363 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
364 assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
365 assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
366 assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
367
368 /* Check the SAI Block Frame parameters */
369 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
370 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
371 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
372 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
373 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
374
375 /* Check the SAI Block Slot parameters */
376 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
377 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
378 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
379 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
380
381 if(hsai->State == HAL_SAI_STATE_RESET)
382 {
383 /* Allocate lock resource and initialize it */
384 hsai->Lock = HAL_UNLOCKED;
385
386 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
387 HAL_SAI_MspInit(hsai);
388 }
389
390 hsai->State = HAL_SAI_STATE_BUSY;
391
392 /* Disable the selected SAI peripheral */
393 SAI_Disable(hsai);
394
395 /* SAI Block Synchro Configuration -----------------------------------------*/
396 SAI_BlockSynchroConfig(hsai);
397
398 /* Configure Master Clock using the following formula :
399 MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
400 FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
401 MCKDIV[3:0] = SAI_CK_x / FS * 512 */
402 if(hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
403 {
404 /* Get SAI clock source based on Source clock selection from RCC */
405 freq = SAI_GetInputClock(hsai);
406
407 /* (saiclocksource x 10) to keep Significant digits */
408 tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U)));
409
410 hsai->Init.Mckdiv = tmpregisterGCR / 10U;
411
412 /* Round result to the nearest integer */
413 if((tmpregisterGCR % 10U) > 8U)
414 {
415 hsai->Init.Mckdiv+= 1U;
416 }
417 }
418
419 /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */
420 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
421 {
422 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U: SAI_xCR1_CKSTR;
423 }
424 else
425 {
426 ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR: 0U;
427 }
428
429 /* SAI Block Configuration -------------------------------------------------*/
430 switch(hsai->Init.Synchro)
431 {
432 case SAI_ASYNCHRONOUS :
433 {
434 syncen_bits = 0U;
435 }
436 break;
437 case SAI_SYNCHRONOUS :
438 {
439 syncen_bits = SAI_xCR1_SYNCEN_0;
440 }
441 break;
442 case SAI_SYNCHRONOUS_EXT_SAI1 :
443 case SAI_SYNCHRONOUS_EXT_SAI2 :
444 {
445 syncen_bits = SAI_xCR1_SYNCEN_1;
446 }
447 break;
448 default:
449 break;
450 }
451 /* SAI CR1 Configuration */
452 hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
453 SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN |\
454 SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
455 SAI_xCR1_NODIV | SAI_xCR1_MCKDIV);
456
457 hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
458 hsai->Init.DataSize | hsai->Init.FirstBit | \
459 ckstr_bits | syncen_bits | \
460 hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
461 hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U));
462
463 /* SAI CR2 Configuration */
464 hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
465 hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
466
467 /* SAI Frame Configuration -----------------------------------------*/
468 hsai->Instance->FRCR&=(~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
469 SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
470 hsai->Instance->FRCR|=((hsai->FrameInit.FrameLength - 1U) |
471 hsai->FrameInit.FSOffset |
472 hsai->FrameInit.FSDefinition |
473 hsai->FrameInit.FSPolarity |
474 ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U));
475
476 /* SAI Block_x SLOT Configuration ------------------------------------------*/
477 /* This register has no meaning in AC 97 and SPDIF audio protocol */
478 hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
479 SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN );
480
481 hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
482 (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) << 8U);
483
484 /* Initialize the error code */
485 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
486
487 /* Initialize the SAI state */
488 hsai->State= HAL_SAI_STATE_READY;
489
490 /* Release Lock */
491 __HAL_UNLOCK(hsai);
492
493 return HAL_OK;
494 }
495
496 /**
497 * @brief DeInitialize the SAI peripheral.
498 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
499 * the configuration information for SAI module.
500 * @retval HAL status
501 */
502 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
503 {
504 /* Check the SAI handle allocation */
505 if(hsai == NULL)
506 {
507 return HAL_ERROR;
508 }
509
510 hsai->State = HAL_SAI_STATE_BUSY;
511
512 /* Disabled All interrupt and clear all the flag */
513 hsai->Instance->IMR = 0U;
514 hsai->Instance->CLRFR = 0xFFFFFFFFU;
515
516 /* Disable the SAI */
517 SAI_Disable(hsai);
518
519 /* Flush the fifo */
520 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
521
522 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
523 HAL_SAI_MspDeInit(hsai);
524
525 /* Initialize the error code */
526 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
527
528 /* Initialize the SAI state */
529 hsai->State = HAL_SAI_STATE_RESET;
530
531 /* Release Lock */
532 __HAL_UNLOCK(hsai);
533
534 return HAL_OK;
535 }
536
537 /**
538 * @brief Initialize the SAI MSP.
539 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
540 * the configuration information for SAI module.
541 * @retval None
542 */
543 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
544 {
545 /* Prevent unused argument(s) compilation warning */
546 UNUSED(hsai);
547
548 /* NOTE : This function should not be modified, when the callback is needed,
549 the HAL_SAI_MspInit could be implemented in the user file
550 */
551 }
552
553 /**
554 * @brief DeInitialize the SAI MSP.
555 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
556 * the configuration information for SAI module.
557 * @retval None
558 */
559 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
560 {
561 /* Prevent unused argument(s) compilation warning */
562 UNUSED(hsai);
563
564 /* NOTE : This function should not be modified, when the callback is needed,
565 the HAL_SAI_MspDeInit could be implemented in the user file
566 */
567 }
568
569 /**
570 * @}
571 */
572
573 /** @defgroup SAI_Exported_Functions_Group2 IO operation functions
574 * @brief Data transfers functions
575 *
576 @verbatim
577 ==============================================================================
578 ##### IO operation functions #####
579 ==============================================================================
580 [..]
581 This subsection provides a set of functions allowing to manage the SAI data
582 transfers.
583
584 (+) There are two modes of transfer:
585 (++) Blocking mode : The communication is performed in the polling mode.
586 The status of all data processing is returned by the same function
587 after finishing transfer.
588 (++) No-Blocking mode : The communication is performed using Interrupts
589 or DMA. These functions return the status of the transfer startup.
590 The end of the data processing will be indicated through the
591 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
592 using DMA mode.
593
594 (+) Blocking mode functions are :
595 (++) HAL_SAI_Transmit()
596 (++) HAL_SAI_Receive()
597
598 (+) Non Blocking mode functions with Interrupt are :
599 (++) HAL_SAI_Transmit_IT()
600 (++) HAL_SAI_Receive_IT()
601
602 (+) Non Blocking mode functions with DMA are :
603 (++) HAL_SAI_Transmit_DMA()
604 (++) HAL_SAI_Receive_DMA()
605
606 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
607 (++) HAL_SAI_TxCpltCallback()
608 (++) HAL_SAI_RxCpltCallback()
609 (++) HAL_SAI_ErrorCallback()
610
611 @endverbatim
612 * @{
613 */
614
615 /**
616 * @brief Transmit an amount of data in blocking mode.
617 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
618 * the configuration information for SAI module.
619 * @param pData Pointer to data buffer
620 * @param Size Amount of data to be sent
621 * @param Timeout Timeout duration
622 * @retval HAL status
623 */
624 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t* pData, uint16_t Size, uint32_t Timeout)
625 {
626 uint32_t tickstart = HAL_GetTick();
627
628 if((pData == NULL ) || (Size == 0))
629 {
630 return HAL_ERROR;
631 }
632
633 if(hsai->State == HAL_SAI_STATE_READY)
634 {
635 /* Process Locked */
636 __HAL_LOCK(hsai);
637
638 hsai->XferSize = Size;
639 hsai->XferCount = Size;
640 hsai->pBuffPtr = pData;
641 hsai->State = HAL_SAI_STATE_BUSY_TX;
642 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
643
644 /* Check if the SAI is already enabled */
645 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
646 {
647 /* fill the fifo with data before to enabled the SAI */
648 SAI_FillFifo(hsai);
649 /* Enable SAI peripheral */
650 __HAL_SAI_ENABLE(hsai);
651 }
652
653 while(hsai->XferCount > 0U)
654 {
655 /* Write data if the FIFO is not full */
656 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
657 {
658 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
659 {
660 hsai->Instance->DR = (*hsai->pBuffPtr++);
661 }
662 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
663 {
664 hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr);
665 hsai->pBuffPtr+= 2U;
666 }
667 else
668 {
669 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
670 hsai->pBuffPtr+= 4U;
671 }
672 hsai->XferCount--;
673 }
674 else
675 {
676 /* Check for the Timeout */
677 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart) > Timeout)))
678 {
679 /* Update error code */
680 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
681
682 /* Clear all the flags */
683 hsai->Instance->CLRFR = 0xFFFFFFFFU;
684
685 /* Disable SAI peripheral */
686 SAI_Disable(hsai);
687
688 /* Flush the fifo */
689 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
690
691 /* Change the SAI state */
692 hsai->State = HAL_SAI_STATE_READY;
693
694 /* Process Unlocked */
695 __HAL_UNLOCK(hsai);
696
697 return HAL_ERROR;
698 }
699 }
700 }
701
702 hsai->State = HAL_SAI_STATE_READY;
703
704 /* Process Unlocked */
705 __HAL_UNLOCK(hsai);
706
707 return HAL_OK;
708 }
709 else
710 {
711 return HAL_BUSY;
712 }
713 }
714
715 /**
716 * @brief Receive an amount of data in blocking mode.
717 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
718 * the configuration information for SAI module.
719 * @param pData Pointer to data buffer
720 * @param Size Amount of data to be received
721 * @param Timeout Timeout duration
722 * @retval HAL status
723 */
724 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
725 {
726 uint32_t tickstart = HAL_GetTick();
727
728 if((pData == NULL ) || (Size == 0))
729 {
730 return HAL_ERROR;
731 }
732
733 if(hsai->State == HAL_SAI_STATE_READY)
734 {
735 /* Process Locked */
736 __HAL_LOCK(hsai);
737
738 hsai->pBuffPtr = pData;
739 hsai->XferSize = Size;
740 hsai->XferCount = Size;
741 hsai->State = HAL_SAI_STATE_BUSY_RX;
742 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
743
744 /* Check if the SAI is already enabled */
745 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
746 {
747 /* Enable SAI peripheral */
748 __HAL_SAI_ENABLE(hsai);
749 }
750
751 /* Receive data */
752 while(hsai->XferCount > 0U)
753 {
754 if((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
755 {
756 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
757 {
758 (*hsai->pBuffPtr++) = hsai->Instance->DR;
759 }
760 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
761 {
762 *((uint16_t*)hsai->pBuffPtr) = hsai->Instance->DR;
763 hsai->pBuffPtr+= 2U;
764 }
765 else
766 {
767 *((uint32_t*)hsai->pBuffPtr) = hsai->Instance->DR;
768 hsai->pBuffPtr+= 4U;
769 }
770 hsai->XferCount--;
771 }
772 else
773 {
774 /* Check for the Timeout */
775 if((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)))
776 {
777 /* Update error code */
778 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
779
780 /* Clear all the flags */
781 hsai->Instance->CLRFR = 0xFFFFFFFFU;
782
783 /* Disable SAI peripheral */
784 SAI_Disable(hsai);
785
786 /* Flush the fifo */
787 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
788
789 /* Change the SAI state */
790 hsai->State = HAL_SAI_STATE_READY;
791
792 /* Process Unlocked */
793 __HAL_UNLOCK(hsai);
794
795 return HAL_ERROR;
796 }
797 }
798 }
799
800 hsai->State = HAL_SAI_STATE_READY;
801
802 /* Process Unlocked */
803 __HAL_UNLOCK(hsai);
804
805 return HAL_OK;
806 }
807 else
808 {
809 return HAL_BUSY;
810 }
811 }
812
813 /**
814 * @brief Transmit an amount of data in non-blocking mode with Interrupt.
815 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
816 * the configuration information for SAI module.
817 * @param pData Pointer to data buffer
818 * @param Size Amount of data to be sent
819 * @retval HAL status
820 */
821 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
822 {
823 if((pData == NULL) || (Size == 0))
824 {
825 return HAL_ERROR;
826 }
827
828 if(hsai->State == HAL_SAI_STATE_READY)
829 {
830 /* Process Locked */
831 __HAL_LOCK(hsai);
832
833 hsai->pBuffPtr = pData;
834 hsai->XferSize = Size;
835 hsai->XferCount = Size;
836 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
837 hsai->State = HAL_SAI_STATE_BUSY_TX;
838
839 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
840 {
841 hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
842 }
843 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
844 {
845 hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
846 }
847 else
848 {
849 hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
850 }
851
852 /* Fill the fifo before starting the communication */
853 SAI_FillFifo(hsai);
854
855 /* Enable FRQ and OVRUDR interrupts */
856 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
857
858 /* Check if the SAI is already enabled */
859 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
860 {
861 /* Enable SAI peripheral */
862 __HAL_SAI_ENABLE(hsai);
863 }
864 /* Process Unlocked */
865 __HAL_UNLOCK(hsai);
866
867 return HAL_OK;
868 }
869 else
870 {
871 return HAL_BUSY;
872 }
873 }
874
875 /**
876 * @brief Receive an amount of data in non-blocking mode with Interrupt.
877 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
878 * the configuration information for SAI module.
879 * @param pData Pointer to data buffer
880 * @param Size Amount of data to be received
881 * @retval HAL status
882 */
883 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
884 {
885 if((pData == NULL) || (Size == 0))
886 {
887 return HAL_ERROR;
888 }
889
890 if(hsai->State == HAL_SAI_STATE_READY)
891 {
892 /* Process Locked */
893 __HAL_LOCK(hsai);
894
895 hsai->pBuffPtr = pData;
896 hsai->XferSize = Size;
897 hsai->XferCount = Size;
898 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
899 hsai->State = HAL_SAI_STATE_BUSY_RX;
900
901 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
902 {
903 hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
904 }
905 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
906 {
907 hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
908 }
909 else
910 {
911 hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
912 }
913
914 /* Enable TXE and OVRUDR interrupts */
915 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
916
917 /* Check if the SAI is already enabled */
918 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
919 {
920 /* Enable SAI peripheral */
921 __HAL_SAI_ENABLE(hsai);
922 }
923
924 /* Process Unlocked */
925 __HAL_UNLOCK(hsai);
926
927 return HAL_OK;
928 }
929 else
930 {
931 return HAL_BUSY;
932 }
933 }
934
935 /**
936 * @brief Pause the audio stream playing from the Media.
937 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
938 * the configuration information for SAI module.
939 * @retval HAL status
940 */
941 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
942 {
943 /* Process Locked */
944 __HAL_LOCK(hsai);
945
946 /* Pause the audio file playing by disabling the SAI DMA requests */
947 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
948
949 /* Process Unlocked */
950 __HAL_UNLOCK(hsai);
951
952 return HAL_OK;
953 }
954
955 /**
956 * @brief Resume the audio stream playing from the Media.
957 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
958 * the configuration information for SAI module.
959 * @retval HAL status
960 */
961 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
962 {
963 /* Process Locked */
964 __HAL_LOCK(hsai);
965
966 /* Enable the SAI DMA requests */
967 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
968
969 /* If the SAI peripheral is still not enabled, enable it */
970 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
971 {
972 /* Enable SAI peripheral */
973 __HAL_SAI_ENABLE(hsai);
974 }
975
976 /* Process Unlocked */
977 __HAL_UNLOCK(hsai);
978
979 return HAL_OK;
980 }
981
982 /**
983 * @brief Stop the audio stream playing from the Media.
984 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
985 * the configuration information for SAI module.
986 * @retval HAL status
987 */
988 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
989 {
990 HAL_StatusTypeDef status = HAL_OK;
991
992 /* Process Locked */
993 __HAL_LOCK(hsai);
994
995 /* Disable the SAI DMA request */
996 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
997
998 /* Abort the SAI Tx DMA Stream */
999 if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1000 {
1001 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1002 {
1003 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1004 if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1005 {
1006 status = HAL_ERROR;
1007 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1008 }
1009 }
1010 }
1011
1012 /* Abort the SAI Rx DMA Stream */
1013 if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1014 {
1015 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1016 {
1017 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1018 if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1019 {
1020 status = HAL_ERROR;
1021 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1022 }
1023 }
1024 }
1025
1026 /* Disable SAI peripheral */
1027 SAI_Disable(hsai);
1028
1029 /* Flush the fifo */
1030 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1031
1032 /* Set hsai state to ready */
1033 hsai->State = HAL_SAI_STATE_READY;
1034
1035 /* Process Unlocked */
1036 __HAL_UNLOCK(hsai);
1037
1038 return status;
1039 }
1040
1041 /**
1042 * @brief Abort the current transfer and disable the SAI.
1043 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1044 * the configuration information for SAI module.
1045 * @retval HAL status
1046 */
1047 HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
1048 {
1049 HAL_StatusTypeDef status = HAL_OK;
1050
1051 /* Process Locked */
1052 __HAL_LOCK(hsai);
1053
1054 /* Check SAI DMA is enabled or not */
1055 if((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1056 {
1057 /* Disable the SAI DMA request */
1058 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
1059
1060 /* Abort the SAI Tx DMA Stream */
1061 if((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX))
1062 {
1063 if(HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
1064 {
1065 /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
1066 if(hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1067 {
1068 status = HAL_ERROR;
1069 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1070 }
1071 }
1072 }
1073
1074 /* Abort the SAI Rx DMA Stream */
1075 if((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX))
1076 {
1077 if(HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
1078 {
1079 /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
1080 if(hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
1081 {
1082 status = HAL_ERROR;
1083 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
1084 }
1085 }
1086 }
1087 }
1088
1089 /* Disabled All interrupt and clear all the flag */
1090 hsai->Instance->IMR = 0U;
1091 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1092
1093 /* Disable SAI peripheral */
1094 SAI_Disable(hsai);
1095
1096 /* Flush the fifo */
1097 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
1098
1099 /* Set hsai state to ready */
1100 hsai->State = HAL_SAI_STATE_READY;
1101
1102 /* Process Unlocked */
1103 __HAL_UNLOCK(hsai);
1104
1105 return status;
1106 }
1107
1108 /**
1109 * @brief Transmit an amount of data in non-blocking mode with DMA.
1110 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1111 * the configuration information for SAI module.
1112 * @param pData Pointer to data buffer
1113 * @param Size Amount of data to be sent
1114 * @retval HAL status
1115 */
1116 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1117 {
1118 if((pData == NULL) || (Size == 0))
1119 {
1120 return HAL_ERROR;
1121 }
1122
1123 if(hsai->State == HAL_SAI_STATE_READY)
1124 {
1125 /* Process Locked */
1126 __HAL_LOCK(hsai);
1127
1128 hsai->pBuffPtr = pData;
1129 hsai->XferSize = Size;
1130 hsai->XferCount = Size;
1131 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1132 hsai->State = HAL_SAI_STATE_BUSY_TX;
1133
1134 /* Set the SAI Tx DMA Half transfer complete callback */
1135 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
1136
1137 /* Set the SAI TxDMA transfer complete callback */
1138 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
1139
1140 /* Set the DMA error callback */
1141 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
1142
1143 /* Set the DMA Tx abort callback */
1144 hsai->hdmatx->XferAbortCallback = NULL;
1145
1146 /* Enable the Tx DMA Stream */
1147 if(HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
1148 {
1149 __HAL_UNLOCK(hsai);
1150 return HAL_ERROR;
1151 }
1152
1153 /* Check if the SAI is already enabled */
1154 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1155 {
1156 /* Enable SAI peripheral */
1157 __HAL_SAI_ENABLE(hsai);
1158 }
1159
1160 /* Enable the interrupts for error handling */
1161 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1162
1163 /* Enable SAI Tx DMA Request */
1164 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1165
1166 /* Process Unlocked */
1167 __HAL_UNLOCK(hsai);
1168
1169 return HAL_OK;
1170 }
1171 else
1172 {
1173 return HAL_BUSY;
1174 }
1175 }
1176
1177 /**
1178 * @brief Receive an amount of data in non-blocking mode with DMA.
1179 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1180 * the configuration information for SAI module.
1181 * @param pData Pointer to data buffer
1182 * @param Size Amount of data to be received
1183 * @retval HAL status
1184 */
1185 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
1186 {
1187 if((pData == NULL) || (Size == 0))
1188 {
1189 return HAL_ERROR;
1190 }
1191
1192 if(hsai->State == HAL_SAI_STATE_READY)
1193 {
1194 /* Process Locked */
1195 __HAL_LOCK(hsai);
1196
1197 hsai->pBuffPtr = pData;
1198 hsai->XferSize = Size;
1199 hsai->XferCount = Size;
1200 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
1201 hsai->State = HAL_SAI_STATE_BUSY_RX;
1202
1203 /* Set the SAI Rx DMA Half transfer complete callback */
1204 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1205
1206 /* Set the SAI Rx DMA transfer complete callback */
1207 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1208
1209 /* Set the DMA error callback */
1210 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1211
1212 /* Set the DMA Rx abort callback */
1213 hsai->hdmarx->XferAbortCallback = NULL;
1214
1215 /* Enable the Rx DMA Stream */
1216 if(HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
1217 {
1218 __HAL_UNLOCK(hsai);
1219 return HAL_ERROR;
1220 }
1221
1222 /* Check if the SAI is already enabled */
1223 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET)
1224 {
1225 /* Enable SAI peripheral */
1226 __HAL_SAI_ENABLE(hsai);
1227 }
1228
1229 /* Enable the interrupts for error handling */
1230 __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
1231
1232 /* Enable SAI Rx DMA Request */
1233 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1234
1235 /* Process Unlocked */
1236 __HAL_UNLOCK(hsai);
1237
1238 return HAL_OK;
1239 }
1240 else
1241 {
1242 return HAL_BUSY;
1243 }
1244 }
1245
1246 /**
1247 * @brief Enable the Tx mute mode.
1248 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1249 * the configuration information for SAI module.
1250 * @param val value sent during the mute @ref SAI_Block_Mute_Value
1251 * @retval HAL status
1252 */
1253 HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
1254 {
1255 assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
1256
1257 if(hsai->State != HAL_SAI_STATE_RESET)
1258 {
1259 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1260 SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val);
1261 return HAL_OK;
1262 }
1263 return HAL_ERROR;
1264 }
1265
1266 /**
1267 * @brief Disable the Tx mute mode.
1268 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1269 * the configuration information for SAI module.
1270 * @retval HAL status
1271 */
1272 HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
1273 {
1274 if(hsai->State != HAL_SAI_STATE_RESET)
1275 {
1276 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
1277 return HAL_OK;
1278 }
1279 return HAL_ERROR;
1280 }
1281
1282 /**
1283 * @brief Enable the Rx mute detection.
1284 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1285 * the configuration information for SAI module.
1286 * @param callback function called when the mute is detected.
1287 * @param counter number a data before mute detection max 63.
1288 * @retval HAL status
1289 */
1290 HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
1291 {
1292 assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
1293
1294 if(hsai->State != HAL_SAI_STATE_RESET)
1295 {
1296 /* set the mute counter */
1297 CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
1298 SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
1299 hsai->mutecallback = callback;
1300 /* enable the IT interrupt */
1301 __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
1302 return HAL_OK;
1303 }
1304 return HAL_ERROR;
1305 }
1306
1307 /**
1308 * @brief Disable the Rx mute detection.
1309 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1310 * the configuration information for SAI module.
1311 * @retval HAL status
1312 */
1313 HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
1314 {
1315 if(hsai->State != HAL_SAI_STATE_RESET)
1316 {
1317 /* set the mutecallback to NULL */
1318 hsai->mutecallback = (SAIcallback)NULL;
1319 /* enable the IT interrupt */
1320 __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
1321 return HAL_OK;
1322 }
1323 return HAL_ERROR;
1324 }
1325
1326 /**
1327 * @brief Handle SAI interrupt request.
1328 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1329 * the configuration information for SAI module.
1330 * @retval None
1331 */
1332 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1333 {
1334 if(hsai->State != HAL_SAI_STATE_RESET)
1335 {
1336 uint32_t itflags = hsai->Instance->SR;
1337 uint32_t itsources = hsai->Instance->IMR;
1338 uint32_t cr1config = hsai->Instance->CR1;
1339 uint32_t tmperror;
1340
1341 /* SAI Fifo request interrupt occured ------------------------------------*/
1342 if(((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
1343 {
1344 hsai->InterruptServiceRoutine(hsai);
1345 }
1346 /* SAI Overrun error interrupt occurred ----------------------------------*/
1347 else if(((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
1348 {
1349 /* Clear the SAI Overrun flag */
1350 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1351
1352 /* Get the SAI error code */
1353 tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
1354
1355 /* Change the SAI error code */
1356 hsai->ErrorCode |= tmperror;
1357
1358 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1359 HAL_SAI_ErrorCallback(hsai);
1360 }
1361 /* SAI mutedet interrupt occurred ----------------------------------*/
1362 else if(((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
1363 {
1364 /* Clear the SAI mutedet flag */
1365 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
1366
1367 /* call the call back function */
1368 if(hsai->mutecallback != (SAIcallback)NULL)
1369 {
1370 /* inform the user that an RX mute event has been detected */
1371 hsai->mutecallback();
1372 }
1373 }
1374 /* SAI AFSDET interrupt occurred ----------------------------------*/
1375 else if(((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
1376 {
1377 /* Change the SAI error code */
1378 hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
1379
1380 /* Check SAI DMA is enabled or not */
1381 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1382 {
1383 /* Abort the SAI DMA Streams */
1384 if(hsai->hdmatx != NULL)
1385 {
1386 /* Set the DMA Tx abort callback */
1387 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1388
1389 /* Abort DMA in IT mode */
1390 HAL_DMA_Abort_IT(hsai->hdmatx);
1391 }
1392 else if(hsai->hdmarx != NULL)
1393 {
1394 /* Set the DMA Rx abort callback */
1395 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1396
1397 /* Abort DMA in IT mode */
1398 HAL_DMA_Abort_IT(hsai->hdmarx);
1399 }
1400 }
1401 else
1402 {
1403 /* Abort SAI */
1404 HAL_SAI_Abort(hsai);
1405
1406 /* Set error callback */
1407 HAL_SAI_ErrorCallback(hsai);
1408 }
1409 }
1410 /* SAI LFSDET interrupt occurred ----------------------------------*/
1411 else if(((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
1412 {
1413 /* Change the SAI error code */
1414 hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
1415
1416 /* Check SAI DMA is enabled or not */
1417 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1418 {
1419 /* Abort the SAI DMA Streams */
1420 if(hsai->hdmatx != NULL)
1421 {
1422 /* Set the DMA Tx abort callback */
1423 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1424
1425 /* Abort DMA in IT mode */
1426 HAL_DMA_Abort_IT(hsai->hdmatx);
1427 }
1428 else if(hsai->hdmarx != NULL)
1429 {
1430 /* Set the DMA Rx abort callback */
1431 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1432
1433 /* Abort DMA in IT mode */
1434 HAL_DMA_Abort_IT(hsai->hdmarx);
1435 }
1436 }
1437 else
1438 {
1439 /* Abort SAI */
1440 HAL_SAI_Abort(hsai);
1441
1442 /* Set error callback */
1443 HAL_SAI_ErrorCallback(hsai);
1444 }
1445 }
1446 /* SAI WCKCFG interrupt occurred ----------------------------------*/
1447 else if(((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
1448 {
1449 /* Change the SAI error code */
1450 hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
1451
1452 /* Check SAI DMA is enabled or not */
1453 if((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
1454 {
1455 /* Abort the SAI DMA Streams */
1456 if(hsai->hdmatx != NULL)
1457 {
1458 /* Set the DMA Tx abort callback */
1459 hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
1460
1461 /* Abort DMA in IT mode */
1462 HAL_DMA_Abort_IT(hsai->hdmatx);
1463 }
1464 else if(hsai->hdmarx != NULL)
1465 {
1466 /* Set the DMA Rx abort callback */
1467 hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
1468
1469 /* Abort DMA in IT mode */
1470 HAL_DMA_Abort_IT(hsai->hdmarx);
1471 }
1472 }
1473 else
1474 {
1475 /* If WCKCFG occurs, SAI audio block is automatically disabled */
1476 /* Disable all interrupts and clear all flags */
1477 hsai->Instance->IMR = 0U;
1478 hsai->Instance->CLRFR = 0xFFFFFFFFU;
1479
1480 /* Set the SAI state to ready to be able to start again the process */
1481 hsai->State = HAL_SAI_STATE_READY;
1482
1483 /* Initialize XferCount */
1484 hsai->XferCount = 0U;
1485
1486 /* SAI error Callback */
1487 HAL_SAI_ErrorCallback(hsai);
1488 }
1489 }
1490 /* SAI CNRDY interrupt occurred ----------------------------------*/
1491 else if(((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
1492 {
1493 /* Clear the SAI CNRDY flag */
1494 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
1495
1496 /* Change the SAI error code */
1497 hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
1498
1499 /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
1500 HAL_SAI_ErrorCallback(hsai);
1501 }
1502 else
1503 {
1504 /* Nothing to do */
1505 }
1506 }
1507 }
1508
1509 /**
1510 * @brief Tx Transfer completed callback.
1511 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1512 * the configuration information for SAI module.
1513 * @retval None
1514 */
1515 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1516 {
1517 /* Prevent unused argument(s) compilation warning */
1518 UNUSED(hsai);
1519
1520 /* NOTE : This function should not be modified, when the callback is needed,
1521 the HAL_SAI_TxCpltCallback could be implemented in the user file
1522 */
1523 }
1524
1525 /**
1526 * @brief Tx Transfer Half completed callback.
1527 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1528 * the configuration information for SAI module.
1529 * @retval None
1530 */
1531 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1532 {
1533 /* Prevent unused argument(s) compilation warning */
1534 UNUSED(hsai);
1535
1536 /* NOTE : This function should not be modified, when the callback is needed,
1537 the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
1538 */
1539 }
1540
1541 /**
1542 * @brief Rx Transfer completed callback.
1543 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1544 * the configuration information for SAI module.
1545 * @retval None
1546 */
1547 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
1548 {
1549 /* Prevent unused argument(s) compilation warning */
1550 UNUSED(hsai);
1551
1552 /* NOTE : This function should not be modified, when the callback is needed,
1553 the HAL_SAI_RxCpltCallback could be implemented in the user file
1554 */
1555 }
1556
1557 /**
1558 * @brief Rx Transfer half completed callback.
1559 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1560 * the configuration information for SAI module.
1561 * @retval None
1562 */
1563 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1564 {
1565 /* Prevent unused argument(s) compilation warning */
1566 UNUSED(hsai);
1567
1568 /* NOTE : This function should not be modified, when the callback is needed,
1569 the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
1570 */
1571 }
1572
1573 /**
1574 * @brief SAI error callback.
1575 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1576 * the configuration information for SAI module.
1577 * @retval None
1578 */
1579 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
1580 {
1581 /* Prevent unused argument(s) compilation warning */
1582 UNUSED(hsai);
1583
1584 /* NOTE : This function should not be modified, when the callback is needed,
1585 the HAL_SAI_ErrorCallback could be implemented in the user file
1586 */
1587 }
1588
1589 /**
1590 * @}
1591 */
1592
1593
1594 /** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions
1595 * @brief Peripheral State functions
1596 *
1597 @verbatim
1598 ===============================================================================
1599 ##### Peripheral State and Errors functions #####
1600 ===============================================================================
1601 [..]
1602 This subsection permits to get in run-time the status of the peripheral
1603 and the data flow.
1604
1605 @endverbatim
1606 * @{
1607 */
1608
1609 /**
1610 * @brief Return the SAI handle state.
1611 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1612 * the configuration information for SAI module.
1613 * @retval HAL state
1614 */
1615 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
1616 {
1617 return hsai->State;
1618 }
1619
1620 /**
1621 * @brief Return the SAI error code.
1622 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1623 * the configuration information for the specified SAI Block.
1624 * @retval SAI Error Code
1625 */
1626 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
1627 {
1628 return hsai->ErrorCode;
1629 }
1630 /**
1631 * @}
1632 */
1633
1634 /**
1635 * @}
1636 */
1637
1638 /** @addtogroup SAI_Private_Functions
1639 * @brief Private functions
1640 * @{
1641 */
1642
1643 /**
1644 * @brief Initialize the SAI I2S protocol according to the specified parameters
1645 * in the SAI_InitTypeDef and create the associated handle.
1646 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1647 * the configuration information for SAI module.
1648 * @param protocol one of the supported protocol.
1649 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
1650 * the configuration information for SAI module.
1651 * @param nbslot number of slot minimum value is 2 and max is 16.
1652 * the value must be a multiple of 2.
1653 * @retval HAL status
1654 */
1655 static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
1656 {
1657 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
1658 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
1659 /* Compute ClockStrobing according AudioMode */
1660 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1661 { /* Transmit */
1662 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1663 }
1664 else
1665 { /* Receive */
1666 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1667 }
1668 hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1669 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
1670 hsai->SlotInit.FirstBitOffset = 0U;
1671 hsai->SlotInit.SlotNumber = nbslot;
1672
1673 /* in IS2 the number of slot must be even */
1674 if((nbslot & 0x1U) != 0U)
1675 {
1676 return HAL_ERROR;
1677 }
1678
1679 switch(protocol)
1680 {
1681 case SAI_I2S_STANDARD :
1682 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1683 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1684 break;
1685 case SAI_I2S_MSBJUSTIFIED :
1686 case SAI_I2S_LSBJUSTIFIED :
1687 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
1688 hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
1689 break;
1690 default :
1691 return HAL_ERROR;
1692 }
1693
1694 /* Frame definition */
1695 switch(datasize)
1696 {
1697 case SAI_PROTOCOL_DATASIZE_16BIT:
1698 hsai->Init.DataSize = SAI_DATASIZE_16;
1699 hsai->FrameInit.FrameLength = 32U*(nbslot/2U);
1700 hsai->FrameInit.ActiveFrameLength = 16U*(nbslot/2U);
1701 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
1702 break;
1703 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
1704 hsai->Init.DataSize = SAI_DATASIZE_16;
1705 hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1706 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1707 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1708 break;
1709 case SAI_PROTOCOL_DATASIZE_24BIT:
1710 hsai->Init.DataSize = SAI_DATASIZE_24;
1711 hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1712 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1713 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1714 break;
1715 case SAI_PROTOCOL_DATASIZE_32BIT:
1716 hsai->Init.DataSize = SAI_DATASIZE_32;
1717 hsai->FrameInit.FrameLength = 64U*(nbslot/2U);
1718 hsai->FrameInit.ActiveFrameLength = 32U*(nbslot/2U);
1719 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1720 break;
1721 default :
1722 return HAL_ERROR;
1723 }
1724 if(protocol == SAI_I2S_LSBJUSTIFIED)
1725 {
1726 if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
1727 {
1728 hsai->SlotInit.FirstBitOffset = 16U;
1729 }
1730 if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
1731 {
1732 hsai->SlotInit.FirstBitOffset = 8U;
1733 }
1734 }
1735 return HAL_OK;
1736 }
1737
1738 /**
1739 * @brief Initialize the SAI PCM protocol according to the specified parameters
1740 * in the SAI_InitTypeDef and create the associated handle.
1741 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1742 * the configuration information for SAI module.
1743 * @param protocol one of the supported protocol
1744 * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
1745 * @param nbslot number of slot minimum value is 1 and the max is 16.
1746 * @retval HAL status
1747 */
1748 static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
1749 {
1750 hsai->Init.Protocol = SAI_FREE_PROTOCOL;
1751 hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
1752 /* Compute ClockStrobing according AudioMode */
1753 if((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1754 { /* Transmit */
1755 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1756 }
1757 else
1758 { /* Receive */
1759 hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1760 }
1761 hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
1762 hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
1763 hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1764 hsai->SlotInit.FirstBitOffset = 0U;
1765 hsai->SlotInit.SlotNumber = nbslot;
1766 hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
1767
1768 switch(protocol)
1769 {
1770 case SAI_PCM_SHORT :
1771 hsai->FrameInit.ActiveFrameLength = 1U;
1772 break;
1773 case SAI_PCM_LONG :
1774 hsai->FrameInit.ActiveFrameLength = 13U;
1775 break;
1776 default :
1777 return HAL_ERROR;
1778 }
1779
1780 switch(datasize)
1781 {
1782 case SAI_PROTOCOL_DATASIZE_16BIT:
1783 hsai->Init.DataSize = SAI_DATASIZE_16;
1784 hsai->FrameInit.FrameLength = 16U * nbslot;
1785 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
1786 break;
1787 case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
1788 hsai->Init.DataSize = SAI_DATASIZE_16;
1789 hsai->FrameInit.FrameLength = 32U * nbslot;
1790 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1791 break;
1792 case SAI_PROTOCOL_DATASIZE_24BIT :
1793 hsai->Init.DataSize = SAI_DATASIZE_24;
1794 hsai->FrameInit.FrameLength = 32U * nbslot;
1795 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1796 break;
1797 case SAI_PROTOCOL_DATASIZE_32BIT:
1798 hsai->Init.DataSize = SAI_DATASIZE_32;
1799 hsai->FrameInit.FrameLength = 32U * nbslot;
1800 hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
1801 break;
1802 default :
1803 return HAL_ERROR;
1804 }
1805
1806 return HAL_OK;
1807 }
1808
1809 /**
1810 * @brief Fill the fifo.
1811 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1812 * the configuration information for SAI module.
1813 * @retval None
1814 */
1815 static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
1816 {
1817 /* fill the fifo with data before to enabled the SAI */
1818 while(((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
1819 {
1820 if((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
1821 {
1822 hsai->Instance->DR = (*hsai->pBuffPtr++);
1823 }
1824 else if(hsai->Init.DataSize <= SAI_DATASIZE_16)
1825 {
1826 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
1827 hsai->pBuffPtr+= 2U;
1828 }
1829 else
1830 {
1831 hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr);
1832 hsai->pBuffPtr+= 4U;
1833 }
1834 hsai->XferCount--;
1835 }
1836 }
1837
1838 /**
1839 * @brief Return the interrupt flag to set according the SAI setup.
1840 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1841 * the configuration information for SAI module.
1842 * @param mode SAI_MODE_DMA or SAI_MODE_IT
1843 * @retval the list of the IT flag to enable
1844 */
1845 static uint32_t SAI_InterruptFlag(SAI_HandleTypeDef *hsai, uint32_t mode)
1846 {
1847 uint32_t tmpIT = SAI_IT_OVRUDR;
1848
1849 if(mode == SAI_MODE_IT)
1850 {
1851 tmpIT|= SAI_IT_FREQ;
1852 }
1853
1854 if((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
1855 ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
1856 {
1857 tmpIT|= SAI_IT_CNRDY;
1858 }
1859
1860 if((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
1861 {
1862 tmpIT|= SAI_IT_AFSDET | SAI_IT_LFSDET;
1863 }
1864 else
1865 {
1866 /* hsai has been configured in master mode */
1867 tmpIT|= SAI_IT_WCKCFG;
1868 }
1869 return tmpIT;
1870 }
1871
1872 /**
1873 * @brief Disable the SAI and wait for the disabling.
1874 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1875 * the configuration information for SAI module.
1876 * @retval None
1877 */
1878 static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
1879 {
1880 register uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock /7U/1000U);
1881 HAL_StatusTypeDef status = HAL_OK;
1882
1883 /* Disable the SAI instance */
1884 __HAL_SAI_DISABLE(hsai);
1885
1886 do
1887 {
1888 /* Check for the Timeout */
1889 if (count-- == 0U)
1890 {
1891 /* Update error code */
1892 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1893 status = HAL_TIMEOUT;
1894 break;
1895 }
1896 } while((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET);
1897
1898 return status;
1899 }
1900
1901 /**
1902 * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
1903 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1904 * the configuration information for SAI module.
1905 * @retval None
1906 */
1907 static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
1908 {
1909 if(hsai->XferCount == 0U)
1910 {
1911 /* Handle the end of the transmission */
1912 /* Disable FREQ and OVRUDR interrupts */
1913 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1914 hsai->State = HAL_SAI_STATE_READY;
1915 HAL_SAI_TxCpltCallback(hsai);
1916 }
1917 else
1918 {
1919 /* Write data on DR register */
1920 hsai->Instance->DR = (*hsai->pBuffPtr++);
1921 hsai->XferCount--;
1922 }
1923 }
1924
1925 /**
1926 * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
1927 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1928 * the configuration information for SAI module.
1929 * @retval None
1930 */
1931 static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
1932 {
1933 if(hsai->XferCount == 0U)
1934 {
1935 /* Handle the end of the transmission */
1936 /* Disable FREQ and OVRUDR interrupts */
1937 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1938 hsai->State = HAL_SAI_STATE_READY;
1939 HAL_SAI_TxCpltCallback(hsai);
1940 }
1941 else
1942 {
1943 /* Write data on DR register */
1944 hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr;
1945 hsai->pBuffPtr+=2U;
1946 hsai->XferCount--;
1947 }
1948 }
1949
1950 /**
1951 * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
1952 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1953 * the configuration information for SAI module.
1954 * @retval None
1955 */
1956 static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
1957 {
1958 if(hsai->XferCount == 0U)
1959 {
1960 /* Handle the end of the transmission */
1961 /* Disable FREQ and OVRUDR interrupts */
1962 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1963 hsai->State = HAL_SAI_STATE_READY;
1964 HAL_SAI_TxCpltCallback(hsai);
1965 }
1966 else
1967 {
1968 /* Write data on DR register */
1969 hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr;
1970 hsai->pBuffPtr+=4U;
1971 hsai->XferCount--;
1972 }
1973 }
1974
1975 /**
1976 * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
1977 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
1978 * the configuration information for SAI module.
1979 * @retval None
1980 */
1981 static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
1982 {
1983 /* Receive data */
1984 (*hsai->pBuffPtr++) = hsai->Instance->DR;
1985 hsai->XferCount--;
1986
1987 /* Check end of the transfer */
1988 if(hsai->XferCount == 0U)
1989 {
1990 /* Disable TXE and OVRUDR interrupts */
1991 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
1992
1993 /* Clear the SAI Overrun flag */
1994 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1995
1996 hsai->State = HAL_SAI_STATE_READY;
1997 HAL_SAI_RxCpltCallback(hsai);
1998 }
1999 }
2000
2001 /**
2002 * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
2003 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2004 * the configuration information for SAI module.
2005 * @retval None
2006 */
2007 static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
2008 {
2009 /* Receive data */
2010 *(uint16_t*)hsai->pBuffPtr = hsai->Instance->DR;
2011 hsai->pBuffPtr+=2U;
2012 hsai->XferCount--;
2013
2014 /* Check end of the transfer */
2015 if(hsai->XferCount == 0U)
2016 {
2017 /* Disable TXE and OVRUDR interrupts */
2018 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2019
2020 /* Clear the SAI Overrun flag */
2021 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2022
2023 hsai->State = HAL_SAI_STATE_READY;
2024 HAL_SAI_RxCpltCallback(hsai);
2025 }
2026 }
2027
2028 /**
2029 * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
2030 * @param hsai pointer to a SAI_HandleTypeDef structure that contains
2031 * the configuration information for SAI module.
2032 * @retval None
2033 */
2034 static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
2035 {
2036 /* Receive data */
2037 *(uint32_t*)hsai->pBuffPtr = hsai->Instance->DR;
2038 hsai->pBuffPtr+=4U;
2039 hsai->XferCount--;
2040
2041 /* Check end of the transfer */
2042 if(hsai->XferCount == 0U)
2043 {
2044 /* Disable TXE and OVRUDR interrupts */
2045 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
2046
2047 /* Clear the SAI Overrun flag */
2048 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
2049
2050 hsai->State = HAL_SAI_STATE_READY;
2051 HAL_SAI_RxCpltCallback(hsai);
2052 }
2053 }
2054
2055 /**
2056 * @brief DMA SAI transmit process complete callback.
2057 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2058 * the configuration information for the specified DMA module.
2059 * @retval None
2060 */
2061 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
2062 {
2063 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
2064
2065 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
2066 {
2067 hsai->XferCount = 0U;
2068
2069 /* Disable SAI Tx DMA Request */
2070 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2071
2072 /* Stop the interrupts error handling */
2073 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2074
2075 hsai->State= HAL_SAI_STATE_READY;
2076 }
2077 HAL_SAI_TxCpltCallback(hsai);
2078 }
2079
2080 /**
2081 * @brief DMA SAI transmit process half complete callback.
2082 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2083 * the configuration information for the specified DMA module.
2084 * @retval None
2085 */
2086 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
2087 {
2088 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2089
2090 HAL_SAI_TxHalfCpltCallback(hsai);
2091 }
2092
2093 /**
2094 * @brief DMA SAI receive process complete callback.
2095 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2096 * the configuration information for the specified DMA module.
2097 * @retval None
2098 */
2099 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
2100 {
2101 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2102 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
2103 {
2104 /* Disable Rx DMA Request */
2105 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
2106 hsai->XferCount = 0U;
2107
2108 /* Stop the interrupts error handling */
2109 __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
2110
2111 hsai->State = HAL_SAI_STATE_READY;
2112 }
2113 HAL_SAI_RxCpltCallback(hsai);
2114 }
2115
2116 /**
2117 * @brief DMA SAI receive process half complete callback
2118 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2119 * the configuration information for the specified DMA module.
2120 * @retval None
2121 */
2122 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
2123 {
2124 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
2125
2126 HAL_SAI_RxHalfCpltCallback(hsai);
2127 }
2128
2129 /**
2130 * @brief DMA SAI communication error callback.
2131 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2132 * the configuration information for the specified DMA module.
2133 * @retval None
2134 */
2135 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
2136 {
2137 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2138
2139 /* Set SAI error code */
2140 hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
2141
2142 if((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE))
2143 {
2144 /* Disable the SAI DMA request */
2145 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2146
2147 /* Disable SAI peripheral */
2148 SAI_Disable(hsai);
2149
2150 /* Set the SAI state ready to be able to start again the process */
2151 hsai->State = HAL_SAI_STATE_READY;
2152
2153 /* Initialize XferCount */
2154 hsai->XferCount = 0U;
2155 }
2156 /* SAI error Callback */
2157 HAL_SAI_ErrorCallback(hsai);
2158 }
2159
2160 /**
2161 * @brief DMA SAI Abort callback.
2162 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
2163 * the configuration information for the specified DMA module.
2164 * @retval None
2165 */
2166 static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
2167 {
2168 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
2169
2170 /* Disable DMA request */
2171 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
2172
2173 /* Disable all interrupts and clear all flags */
2174 hsai->Instance->IMR = 0U;
2175 hsai->Instance->CLRFR = 0xFFFFFFFFU;
2176
2177 if(hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
2178 {
2179 /* Disable SAI peripheral */
2180 SAI_Disable(hsai);
2181
2182 /* Flush the fifo */
2183 SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
2184 }
2185 /* Set the SAI state to ready to be able to start again the process */
2186 hsai->State = HAL_SAI_STATE_READY;
2187
2188 /* Initialize XferCount */
2189 hsai->XferCount = 0U;
2190
2191 /* SAI error Callback */
2192 HAL_SAI_ErrorCallback(hsai);
2193 }
2194
2195 /**
2196 * @}
2197 */
2198
2199 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */
2200 #endif /* HAL_SAI_MODULE_ENABLED */
2201 /**
2202 * @}
2203 */
2204
2205 /**
2206 * @}
2207 */
2208
2209 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/