source: asp3_wo_tecs/trunk/arch/arm_m_gcc/stm32f4xx_stm32cube/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c@ 308

Last change on this file since 308 was 303, checked in by ertl-honda, 7 years ago

nucleo_f401re依存部の追加

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