]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_hal_sai.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32F4 / stm32f4xx_hal_sai.c
1 /**
2 ******************************************************************************
3 * @file stm32f4xx_hal_sai.c
4 * @author MCD Application Team
5 * @version V1.1.0
6 * @date 19-June-2014
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 (@) Make sure that either:
53 (+@) I2S PLL is configured or
54 (+@) SAI PLL is configured or
55 (+@) External clock source is configured after setting correctly
56 the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file.
57
58 [..]
59 (@) In master Tx mode: enabling the audio block immediately generates the bit clock
60 for the external slaves even if there is no data in the FIFO, However FS signal
61 generation is conditioned by the presence of data in the FIFO.
62
63 [..]
64 (@) In master Rx mode: enabling the audio block immediately generates the bit clock
65 and FS signal for the external slaves.
66
67 [..]
68 (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
69 (+@) First bit Offset <= (SLOT size - Data size)
70 (+@) Data size <= SLOT size
71 (+@) Number of SLOT x SLOT size = Frame length
72 (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
73
74 [..]
75 Three operation modes are available within this driver :
76
77 *** Polling mode IO operation ***
78 =================================
79 [..]
80 (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
81 (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
82
83 *** Interrupt mode IO operation ***
84 ===================================
85 [..]
86 (+) Send an amount of data in non blocking mode using HAL_SAI_Transmit_IT()
87 (+) At transmission end of transfer HAL_SAI_TxCpltCallback is executed and user can
88 add his own code by customization of function pointer HAL_SAI_TxCpltCallback
89 (+) Receive an amount of data in non blocking mode using HAL_SAI_Receive_IT()
90 (+) At reception end of transfer HAL_SAI_RxCpltCallback is executed and user can
91 add his own code by customization of function pointer HAL_SAI_RxCpltCallback
92 (+) In case of transfer Error, HAL_SAI_ErrorCallback() function is executed and user can
93 add his own code by customization of function pointer HAL_SAI_ErrorCallback
94
95 *** DMA mode IO operation ***
96 ==============================
97 [..]
98 (+) Send an amount of data in non blocking mode (DMA) using HAL_SAI_Transmit_DMA()
99 (+) At transmission end of transfer HAL_SAI_TxCpltCallback is executed and user can
100 add his own code by customization of function pointer HAL_SAI_TxCpltCallback
101 (+) Receive an amount of data in non blocking mode (DMA) using HAL_SAI_Receive_DMA()
102 (+) At reception end of transfer HAL_SAI_RxCpltCallback is executed and user can
103 add his own code by customization of function pointer HAL_SAI_RxCpltCallback
104 (+) In case of transfer Error, HAL_SAI_ErrorCallback() function is executed and user can
105 add his own code by customization of function pointer HAL_SAI_ErrorCallback
106 (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
107 (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
108 (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
109
110 *** SAI HAL driver macros list ***
111 =============================================
112 [..]
113 Below the list of most used macros in USART HAL driver :
114
115 (+) __HAL_SAI_ENABLE: Enable the SAI peripheral
116 (+) __HAL_SAI_DISABLE: Disable the SAI peripheral
117 (+) __HAL_SAI_ENABLE_IT : Enable the specified SAI interrupts
118 (+) __HAL_SAI_DISABLE_IT : Disable the specified SAI interrupts
119 (+) __HAL_SAI_GET_IT_SOURCE: Check if the specified SAI interrupt source is
120 enabled or disabled
121 (+) __HAL_SAI_GET_FLAG: Check whether the specified SAI flag is set or not
122
123 @endverbatim
124 ******************************************************************************
125 * @attention
126 *
127 * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
128 *
129 * Redistribution and use in source and binary forms, with or without modification,
130 * are permitted provided that the following conditions are met:
131 * 1. Redistributions of source code must retain the above copyright notice,
132 * this list of conditions and the following disclaimer.
133 * 2. Redistributions in binary form must reproduce the above copyright notice,
134 * this list of conditions and the following disclaimer in the documentation
135 * and/or other materials provided with the distribution.
136 * 3. Neither the name of STMicroelectronics nor the names of its contributors
137 * may be used to endorse or promote products derived from this software
138 * without specific prior written permission.
139 *
140 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
141 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
142 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
143 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
144 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
145 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
146 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
147 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
148 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
149 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
150 *
151 ******************************************************************************
152 */
153
154 /* Includes ------------------------------------------------------------------*/
155 #include "stm32f4xx_hal.h"
156
157 /** @addtogroup STM32F4xx_HAL_Driver
158 * @{
159 */
160
161 /** @defgroup SAI
162 * @brief SAI HAL module driver
163 * @{
164 */
165
166 #ifdef HAL_SAI_MODULE_ENABLED
167
168 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
169
170 /* Private typedef -----------------------------------------------------------*/
171 /* Private define ------------------------------------------------------------*/
172 /* SAI registers Masks */
173 #define CR1_CLEAR_MASK ((uint32_t)0xFF07C010)
174 #define FRCR_CLEAR_MASK ((uint32_t)0xFFF88000)
175 #define SLOTR_CLEAR_MASK ((uint32_t)0x0000F020)
176
177 #define SAI_TIMEOUT_VALUE 10
178 /* Private macro -------------------------------------------------------------*/
179 /* Private variables ---------------------------------------------------------*/
180 /* Private function prototypes -----------------------------------------------*/
181 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
182 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
183 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
184 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
185 static void SAI_DMAError(DMA_HandleTypeDef *hdma);
186
187 /* Private functions ---------------------------------------------------------*/
188
189 /** @defgroup SAI_Private_Functions
190 * @{
191 */
192
193 /** @defgroup SAI_Group1 Initialization and de-initialization functions
194 * @brief Initialization and Configuration functions
195 *
196 @verbatim
197 ===============================================================================
198 ##### Initialization and de-initialization functions #####
199 ===============================================================================
200 [..] This subsection provides a set of functions allowing to initialize and
201 de-initialize the SAIx peripheral:
202
203 (+) User must implement HAL_SAI_MspInit() function in which he configures
204 all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
205
206 (+) Call the function HAL_SAI_Init() to configure the selected device with
207 the selected configuration:
208 (++) Mode (Master/slave TX/RX)
209 (++) Protocol
210 (++) Data Size
211 (++) MCLK Output
212 (++) Audio frequency
213 (++) FIFO Threshold
214 (++) Frame Config
215 (++) Slot Config
216
217 (+) Call the function HAL_SAI_DeInit() to restore the default configuration
218 of the selected SAI peripheral.
219
220 @endverbatim
221 * @{
222 */
223
224 /**
225 * @brief Initializes the SAI according to the specified parameters
226 * in the SAI_InitTypeDef and create the associated handle.
227 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
228 * the configuration information for SAI module.
229 * @retval HAL status
230 */
231 HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
232 {
233 uint32_t tmpreg = 0;
234 uint32_t tmpclock = 0, tmp2clock = 0;
235 /* This variable used to store the VCO Input (value in Hz) */
236 uint32_t vcoinput = 0;
237 /* This variable used to store the SAI_CK_x (value in Hz) */
238 uint32_t saiclocksource = 0;
239
240 /* Check the SAI handle allocation */
241 if(hsai == HAL_NULL)
242 {
243 return HAL_ERROR;
244 }
245
246 /* Check the SAI Block parameters */
247 assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
248 assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
249 assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
250 assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
251 assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
252 assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
253 assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
254 assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
255 assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
256 assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
257
258 /* Check the SAI Block Frame parameters */
259 assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
260 assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
261 assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
262 assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
263 assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
264
265 /* Check the SAI Block Slot parameters */
266 assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
267 assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
268 assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
269 assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
270
271 if(hsai->State == HAL_SAI_STATE_RESET)
272 {
273 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
274 HAL_SAI_MspInit(hsai);
275 }
276
277 hsai->State = HAL_SAI_STATE_BUSY;
278
279 /* Disable the selected SAI peripheral */
280 __HAL_SAI_DISABLE(hsai);
281
282 /* SAI Block Configuration ------------------------------------------------------------*/
283 /* SAI Block_x CR1 Configuration */
284 /* Get the SAI Block_x CR1 value */
285 tmpreg = hsai->Instance->CR1;
286 /* Clear MODE, PRTCFG, DS, LSBFIRST, CKSTR, SYNCEN, OUTDRIV, NODIV, and MCKDIV bits */
287 tmpreg &= CR1_CLEAR_MASK;
288 /* Configure SAI_Block_x: Audio Protocol, Data Size, first transmitted bit, Clock strobing
289 edge, Synchronization mode, Output drive, Master Divider and FIFO level */
290 /* Set PRTCFG bits according to Protocol value */
291 /* Set DS bits according to DataSize value */
292 /* Set LSBFIRST bit according to FirstBit value */
293 /* Set CKSTR bit according to ClockStrobing value */
294 /* Set SYNCEN bit according to Synchro value */
295 /* Set OUTDRIV bit according to OutputDrive value */
296 /* Set NODIV bit according to NoDivider value */
297 tmpreg |= (uint32_t)(hsai->Init.Protocol |
298 hsai->Init.AudioMode |
299 hsai->Init.DataSize |
300 hsai->Init.FirstBit |
301 hsai->Init.ClockStrobing |
302 hsai->Init.Synchro |
303 hsai->Init.OutputDrive |
304 hsai->Init.NoDivider);
305 /* Write to SAI_Block_x CR1 */
306 hsai->Instance->CR1 = tmpreg;
307
308 /* SAI Block_x CR2 Configuration */
309 /* Get the SAIBlock_x CR2 value */
310 tmpreg = hsai->Instance->CR2;
311 /* Clear FTH bits */
312 tmpreg &= ~(SAI_xCR2_FTH);
313 /* Configure the FIFO Level */
314 /* Set FTH bits according to SAI_FIFOThreshold value */
315 tmpreg |= (uint32_t)(hsai->Init.FIFOThreshold);
316 /* Write to SAI_Block_x CR2 */
317 hsai->Instance->CR2 = tmpreg;
318
319 /* SAI Block_x Frame Configuration -----------------------------------------*/
320 /* Get the SAI Block_x FRCR value */
321 tmpreg = hsai->Instance->FRCR;
322 /* Clear FRL, FSALL, FSDEF, FSPOL, FSOFF bits */
323 tmpreg &= FRCR_CLEAR_MASK;
324 /* Configure SAI_Block_x Frame: Frame Length, Active Frame Length, Frame Synchronization
325 Definition, Frame Synchronization Polarity and Frame Synchronization Polarity */
326 /* Set FRL bits according to SAI_FrameLength value */
327 /* Set FSALL bits according to SAI_ActiveFrameLength value */
328 /* Set FSDEF bit according to SAI_FSDefinition value */
329 /* Set FSPOL bit according to SAI_FSPolarity value */
330 /* Set FSOFF bit according to SAI_FSOffset value */
331 tmpreg |= (uint32_t)((uint32_t)(hsai->FrameInit.FrameLength - 1) |
332 hsai->FrameInit.FSOffset |
333 hsai->FrameInit.FSDefinition |
334 hsai->FrameInit.FSPolarity |
335 (uint32_t)((hsai->FrameInit.ActiveFrameLength - 1) << 8));
336
337 /* Write to SAI_Block_x FRCR */
338 hsai->Instance->FRCR = tmpreg;
339
340 /* SAI Block_x SLOT Configuration ------------------------------------------*/
341 /* Get the SAI Block_x SLOTR value */
342 tmpreg = hsai->Instance->SLOTR;
343 /* Clear FBOFF, SLOTSZ, NBSLOT, SLOTEN bits */
344 tmpreg &= SLOTR_CLEAR_MASK;
345 /* Configure SAI_Block_x Slot: First bit offset, Slot size, Number of Slot in
346 audio frame and slots activated in audio frame */
347 /* Set FBOFF bits according to SAI_FirstBitOffset value */
348 /* Set SLOTSZ bits according to SAI_SlotSize value */
349 /* Set NBSLOT bits according to SAI_SlotNumber value */
350 /* Set SLOTEN bits according to SAI_SlotActive value */
351 tmpreg |= (uint32_t)(hsai->SlotInit.FirstBitOffset |
352 hsai->SlotInit.SlotSize |
353 hsai->SlotInit.SlotActive |
354 (uint32_t)((hsai->SlotInit.SlotNumber - 1) << 8));
355
356 /* Write to SAI_Block_x SLOTR */
357 hsai->Instance->SLOTR = tmpreg;
358
359 /* SAI Block_x Clock Configuration -----------------------------------------*/
360 /* Check the Clock parameters */
361 assert_param(IS_SAI_CLK_SOURCE(hsai->Init.ClockSource));
362
363 /* SAI Block clock source selection */
364 if(hsai->Instance == SAI1_Block_A)
365 {
366 __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(hsai->Init.ClockSource);
367 }
368 else
369 {
370 __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG((uint32_t)(hsai->Init.ClockSource << 2));
371 }
372
373 /* VCO Input Clock value calculation */
374 if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
375 {
376 /* In Case the PLL Source is HSI (Internal Clock) */
377 vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
378 }
379 else
380 {
381 /* In Case the PLL Source is HSE (External Clock) */
382 vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
383 }
384
385 /* SAI_CLK_x : SAI Block Clock configuration for different clock sources selected */
386 if(hsai->Init.ClockSource == SAI_CLKSOURCE_PLLSAI)
387 {
388 /* Configure the PLLI2S division factor */
389 /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */
390 /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
391 /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
392 tmpreg = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24;
393 saiclocksource = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6))/(tmpreg);
394
395 /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
396 tmpreg = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8) + 1);
397 saiclocksource = saiclocksource/(tmpreg);
398
399 }
400 else if(hsai->Init.ClockSource == SAI_CLKSOURCE_PLLI2S)
401 {
402 /* Configure the PLLI2S division factor */
403 /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */
404 /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
405 /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
406 tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24;
407 saiclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6))/(tmpreg);
408
409 /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
410 tmpreg = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1);
411 saiclocksource = saiclocksource/(tmpreg);
412 }
413 else /* sConfig->ClockSource == SAI_CLKSource_Ext */
414 {
415 /* Enable the External Clock selection */
416 __HAL_RCC_I2SCLK(RCC_I2SCLKSOURCE_EXT);
417
418 saiclocksource = EXTERNAL_CLOCK_VALUE;
419 }
420
421 /* Configure Master Clock using the following formula :
422 MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS
423 FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256
424 MCKDIV[3:0] = SAI_CK_x / FS * 512 */
425 if(hsai->Init.NoDivider == SAI_MASTERDIVIDER_ENABLED)
426 {
427 /* (saiclocksource x 10) to keep Significant digits */
428 tmpclock = (((saiclocksource * 10) / ((hsai->Init.AudioFrequency) * 512)));
429
430 /* Get the result of modulo division */
431 tmp2clock = (tmpclock % 10);
432
433 /* Round result to the nearest integer*/
434 if (tmp2clock > 8)
435 {
436 tmpclock = ((tmpclock / 10) + 1);
437 }
438 else
439 {
440 tmpclock = (tmpclock / 10);
441 }
442 /*Set MCKDIV value in CR1 register*/
443 hsai->Instance->CR1 |= (tmpclock << 20);
444
445 }
446
447 /* Initialise the error code */
448 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
449
450 /* Initialize the SAI state */
451 hsai->State= HAL_SAI_STATE_READY;
452
453 return HAL_OK;
454 }
455
456 /**
457 * @brief DeInitializes the SAI peripheral.
458 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
459 * the configuration information for SAI module.
460 * @retval HAL status
461 */
462 HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
463 {
464 /* Check the SAI handle allocation */
465 if(hsai == HAL_NULL)
466 {
467 return HAL_ERROR;
468 }
469
470 hsai->State = HAL_SAI_STATE_BUSY;
471
472 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
473 HAL_SAI_MspDeInit(hsai);
474
475 /* Initialize the error code */
476 hsai->ErrorCode = HAL_SAI_ERROR_NONE;
477
478 /* Initialize the SAI state */
479 hsai->State = HAL_SAI_STATE_RESET;
480
481 /* Release Lock */
482 __HAL_UNLOCK(hsai);
483
484 return HAL_OK;
485 }
486
487 /**
488 * @brief SAI MSP Init.
489 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
490 * the configuration information for SAI module.
491 * @retval None
492 */
493 __weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
494 {
495 /* NOTE : This function Should not be modified, when the callback is needed,
496 the HAL_SAI_MspInit could be implemented in the user file
497 */
498 }
499
500 /**
501 * @brief SAI MSP DeInit.
502 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
503 * the configuration information for SAI module.
504 * @retval None
505 */
506 __weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
507 {
508 /* NOTE : This function Should not be modified, when the callback is needed,
509 the HAL_SAI_MspDeInit could be implemented in the user file
510 */
511 }
512
513 /**
514 * @}
515 */
516
517 /** @defgroup SAI_Group2 IO operation functions
518 * @brief Data transfers functions
519 *
520 @verbatim
521 ===============================================================================
522 ##### IO operation functions #####
523 ===============================================================================
524 [..]
525 This subsection provides a set of functions allowing to manage the SAI data
526 transfers.
527
528 (+) There are two modes of transfer:
529 (++) Blocking mode : The communication is performed in the polling mode.
530 The status of all data processing is returned by the same function
531 after finishing transfer.
532 (++) No-Blocking mode : The communication is performed using Interrupts
533 or DMA. These functions return the status of the transfer startup.
534 The end of the data processing will be indicated through the
535 dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when
536 using DMA mode.
537
538 (+) Blocking mode functions are :
539 (++) HAL_SAI_Transmit()
540 (++) HAL_SAI_Receive()
541 (++) HAL_SAI_TransmitReceive()
542
543 (+) Non Blocking mode functions with Interrupt are :
544 (++) HAL_SAI_Transmit_IT()
545 (++) HAL_SAI_Receive_IT()
546 (++) HAL_SAI_TransmitReceive_IT()
547
548 (+) Non Blocking mode functions with DMA are :
549 (++) HAL_SAI_Transmit_DMA()
550 (++) HAL_SAI_Receive_DMA()
551 (++) HAL_SAI_TransmitReceive_DMA()
552
553 (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
554 (++) HAL_SAI_TxCpltCallback()
555 (++) HAL_SAI_RxCpltCallback()
556 (++) HAL_SAI_ErrorCallback()
557
558 @endverbatim
559 * @{
560 */
561
562 /**
563 * @brief Transmits an amount of data in blocking mode.
564 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
565 * the configuration information for SAI module.
566 * @param pData: Pointer to data buffer
567 * @param Size: Amount of data to be sent
568 * @param Timeout: Timeout duration
569 * @retval HAL status
570 */
571 HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint16_t* pData, uint16_t Size, uint32_t Timeout)
572 {
573 uint32_t tickstart = 0;
574
575 if((pData == HAL_NULL ) || (Size == 0))
576 {
577 return HAL_ERROR;
578 }
579
580 if(hsai->State == HAL_SAI_STATE_READY)
581 {
582 /* Process Locked */
583 __HAL_LOCK(hsai);
584
585 hsai->State = HAL_SAI_STATE_BUSY_TX;
586
587 /* Check if the SAI is already enabled */
588 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
589 {
590 /* Enable SAI peripheral */
591 __HAL_SAI_ENABLE(hsai);
592 }
593
594 while(Size > 0)
595 {
596 /* Get tick */
597 tickstart = HAL_GetTick();
598
599 /* Wait the FIFO to be empty */
600 while(__HAL_SAI_GET_FLAG(hsai, SAI_xSR_FREQ) == RESET)
601 {
602 /* Check for the Timeout */
603 if(Timeout != HAL_MAX_DELAY)
604 {
605 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
606 {
607 /* Update error code */
608 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
609
610 /* Process Unlocked */
611 __HAL_UNLOCK(hsai);
612
613 /* Change the SAI state */
614 hsai->State = HAL_SAI_STATE_TIMEOUT;
615
616 return HAL_TIMEOUT;
617 }
618 }
619 }
620 hsai->Instance->DR = (*pData++);
621 Size--;
622 }
623
624 hsai->State = HAL_SAI_STATE_READY;
625
626 /* Process Unlocked */
627 __HAL_UNLOCK(hsai);
628
629 return HAL_OK;
630 }
631 else
632 {
633 return HAL_BUSY;
634 }
635 }
636
637 /**
638 * @brief Receives an amount of data in blocking mode.
639 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
640 * the configuration information for SAI module.
641 * @param pData: Pointer to data buffer
642 * @param Size: Amount of data to be received
643 * @param Timeout: Timeout duration
644 * @retval HAL status
645 */
646 HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size, uint32_t Timeout)
647 {
648 uint32_t tickstart = 0;
649
650 if((pData == HAL_NULL ) || (Size == 0))
651 {
652 return HAL_ERROR;
653 }
654
655 if(hsai->State == HAL_SAI_STATE_READY)
656 {
657 /* Process Locked */
658 __HAL_LOCK(hsai);
659
660 hsai->State = HAL_SAI_STATE_BUSY_RX;
661
662 /* Check if the SAI is already enabled */
663 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
664 {
665 /* Enable SAI peripheral */
666 __HAL_SAI_ENABLE(hsai);
667 }
668
669 /* Receive data */
670 while(Size > 0)
671 {
672 /* Get tick */
673 tickstart = HAL_GetTick();
674
675 /* Wait until RXNE flag is set */
676 while(__HAL_SAI_GET_FLAG(hsai, SAI_xSR_FREQ) == RESET)
677 {
678 /* Check for the Timeout */
679 if(Timeout != HAL_MAX_DELAY)
680 {
681 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
682 {
683 /* Update error code */
684 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
685
686 /* Process Unlocked */
687 __HAL_UNLOCK(hsai);
688
689 /* Change the SAI state */
690 hsai->State = HAL_SAI_STATE_TIMEOUT;
691
692 return HAL_TIMEOUT;
693 }
694 }
695 }
696
697 (*pData++) = hsai->Instance->DR;
698 Size--;
699 }
700
701 hsai->State = HAL_SAI_STATE_READY;
702
703 /* Process Unlocked */
704 __HAL_UNLOCK(hsai);
705
706 return HAL_OK;
707 }
708 else
709 {
710 return HAL_BUSY;
711 }
712 }
713
714 /**
715 * @brief Transmits an amount of data in no-blocking mode with Interrupt.
716 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
717 * the configuration information for SAI module.
718 * @param pData: Pointer to data buffer
719 * @param Size: Amount of data to be sent
720 * @retval HAL status
721 */
722 HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size)
723 {
724 if(hsai->State == HAL_SAI_STATE_READY)
725 {
726 if((pData == HAL_NULL) || (Size == 0))
727 {
728 return HAL_ERROR;
729 }
730
731 hsai->pTxBuffPtr = pData;
732 hsai->TxXferSize = Size;
733 hsai->TxXferCount = Size;
734
735 /* Process Locked */
736 __HAL_LOCK(hsai);
737
738 hsai->State = HAL_SAI_STATE_BUSY_TX;
739
740 /* Transmit data */
741 hsai->Instance->DR = (*hsai->pTxBuffPtr++);
742 hsai->TxXferCount--;
743
744 /* Process Unlocked */
745 __HAL_UNLOCK(hsai);
746
747 /* Enable FRQ and OVRUDR interrupts */
748 __HAL_SAI_ENABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));
749
750 /* Check if the SAI is already enabled */
751 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
752 {
753 /* Enable SAI peripheral */
754 __HAL_SAI_ENABLE(hsai);
755 }
756
757
758 return HAL_OK;
759 }
760 else if(hsai->State == HAL_SAI_STATE_BUSY_TX)
761 {
762 /* Process Locked */
763 __HAL_LOCK(hsai);
764
765 /* Transmit data */
766 hsai->Instance->DR = (*hsai->pTxBuffPtr++);
767
768 hsai->TxXferCount--;
769
770 if(hsai->TxXferCount == 0)
771 {
772 /* Disable FREQ and OVRUDR interrupts */
773 __HAL_SAI_DISABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));
774
775 hsai->State = HAL_SAI_STATE_READY;
776
777 HAL_SAI_TxCpltCallback(hsai);
778 }
779
780 /* Process Unlocked */
781 __HAL_UNLOCK(hsai);
782
783 return HAL_OK;
784 }
785
786 else
787 {
788 return HAL_BUSY;
789 }
790 }
791
792 /**
793 * @brief Receives an amount of data in no-blocking mode with Interrupt.
794 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
795 * the configuration information for SAI module.
796 * @param pData: Pointer to data buffer
797 * @param Size: Amount of data to be received
798 * @retval HAL status
799 */
800 HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size)
801 {
802 if(hsai->State == HAL_SAI_STATE_READY)
803 {
804 if((pData == HAL_NULL) || (Size == 0))
805 {
806 return HAL_ERROR;
807 }
808
809 hsai->pRxBuffPtr = pData;
810 hsai->RxXferSize = Size;
811 hsai->RxXferCount = Size;
812
813 /* Process Locked */
814 __HAL_LOCK(hsai);
815
816 hsai->State = HAL_SAI_STATE_BUSY_RX;
817
818 /* Enable TXE and OVRUDR interrupts */
819 __HAL_SAI_ENABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));
820
821 /* Check if the SAI is already enabled */
822 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
823 {
824 /* Enable SAI peripheral */
825 __HAL_SAI_ENABLE(hsai);
826 }
827
828 /* Process Unlocked */
829 __HAL_UNLOCK(hsai);
830
831 return HAL_OK;
832 }
833 else if(hsai->State == HAL_SAI_STATE_BUSY_RX)
834 {
835 /* Process Locked */
836 __HAL_LOCK(hsai);
837
838 /* Receive data */
839 (*hsai->pRxBuffPtr++) = hsai->Instance->DR;
840
841 hsai->RxXferCount--;
842
843 if(hsai->RxXferCount == 0)
844 {
845 /* Disable TXE and OVRUDR interrupts */
846 __HAL_SAI_DISABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));
847
848 hsai->State = HAL_SAI_STATE_READY;
849 HAL_SAI_RxCpltCallback(hsai);
850 }
851
852 /* Process Unlocked */
853 __HAL_UNLOCK(hsai);
854
855 return HAL_OK;
856 }
857
858 else
859 {
860 return HAL_BUSY;
861 }
862 }
863
864 /**
865 * @brief Pauses the audio stream playing from the Media.
866 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
867 * the configuration information for SAI module.
868 * @retval HAL status
869 */
870 HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
871 {
872 /* Process Locked */
873 __HAL_LOCK(hsai);
874
875 /* Pause the audio file playing by disabling the SAI DMA requests */
876 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
877
878
879 /* Process Unlocked */
880 __HAL_UNLOCK(hsai);
881
882 return HAL_OK;
883 }
884
885 /**
886 * @brief Resumes the audio stream playing from the Media.
887 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
888 * the configuration information for SAI module.
889 * @retval HAL status
890 */
891 HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
892 {
893 /* Process Locked */
894 __HAL_LOCK(hsai);
895
896 /* Enable the SAI DMA requests */
897 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
898
899
900 /* If the SAI peripheral is still not enabled, enable it */
901 if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0)
902 {
903 /* Enable SAI peripheral */
904 __HAL_SAI_ENABLE(hsai);
905 }
906
907 /* Process Unlocked */
908 __HAL_UNLOCK(hsai);
909
910 return HAL_OK;
911 }
912
913 /**
914 * @brief Stops the audio stream playing from the Media.
915 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
916 * the configuration information for SAI module.
917 * @retval HAL status
918 */
919 HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
920 {
921 /* Process Locked */
922 __HAL_LOCK(hsai);
923
924 /* Disable the SAI DMA request */
925 hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
926
927 /* Abort the SAI DMA Tx Stream */
928 if(hsai->hdmatx != HAL_NULL)
929 {
930 HAL_DMA_Abort(hsai->hdmatx);
931 }
932 /* Abort the SAI DMA Rx Stream */
933 if(hsai->hdmarx != HAL_NULL)
934 {
935 HAL_DMA_Abort(hsai->hdmarx);
936 }
937
938 /* Disable SAI peripheral */
939 __HAL_SAI_DISABLE(hsai);
940
941 hsai->State = HAL_SAI_STATE_READY;
942
943 /* Process Unlocked */
944 __HAL_UNLOCK(hsai);
945
946 return HAL_OK;
947 }
948 /**
949 * @brief Transmits an amount of data in no-blocking mode with DMA.
950 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
951 * the configuration information for SAI module.
952 * @param pData: Pointer to data buffer
953 * @param Size: Amount of data to be sent
954 * @retval HAL status
955 */
956 HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size)
957 {
958 uint32_t *tmp;
959
960 if((pData == HAL_NULL) || (Size == 0))
961 {
962 return HAL_ERROR;
963 }
964
965 if(hsai->State == HAL_SAI_STATE_READY)
966 {
967 hsai->pTxBuffPtr = pData;
968 hsai->TxXferSize = Size;
969 hsai->TxXferCount = Size;
970
971 /* Process Locked */
972 __HAL_LOCK(hsai);
973
974 hsai->State = HAL_SAI_STATE_BUSY_TX;
975
976 /* Set the SAI Tx DMA Half transfert complete callback */
977 hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
978
979 /* Set the SAI TxDMA transfer complete callback */
980 hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
981
982 /* Set the DMA error callback */
983 hsai->hdmatx->XferErrorCallback = SAI_DMAError;
984
985 /* Enable the Tx DMA Stream */
986 tmp = (uint32_t*)&pData;
987 HAL_DMA_Start_IT(hsai->hdmatx, *(uint32_t*)tmp, (uint32_t)&hsai->Instance->DR, hsai->TxXferSize);
988
989 /* Check if the SAI is already enabled */
990 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
991 {
992 /* Enable SAI peripheral */
993 __HAL_SAI_ENABLE(hsai);
994 }
995
996 /* Enable SAI Tx DMA Request */
997 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
998
999 /* Process Unlocked */
1000 __HAL_UNLOCK(hsai);
1001
1002 return HAL_OK;
1003 }
1004 else
1005 {
1006 return HAL_BUSY;
1007 }
1008 }
1009
1010 /**
1011 * @brief Receives an amount of data in no-blocking mode with DMA.
1012 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1013 * the configuration information for SAI module.
1014 * @param pData: Pointer to data buffer
1015 * @param Size: Amount of data to be received
1016 * @retval HAL status
1017 */
1018 HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size)
1019 {
1020 uint32_t *tmp;
1021
1022 if((pData == HAL_NULL) || (Size == 0))
1023 {
1024 return HAL_ERROR;
1025 }
1026
1027 if(hsai->State == HAL_SAI_STATE_READY)
1028 {
1029 hsai->pRxBuffPtr = pData;
1030 hsai->RxXferSize = Size;
1031 hsai->RxXferCount = Size;
1032
1033 /* Process Locked */
1034 __HAL_LOCK(hsai);
1035
1036 hsai->State = HAL_SAI_STATE_BUSY_RX;
1037
1038 /* Set the SAI Rx DMA Half transfert complete callback */
1039 hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
1040
1041 /* Set the SAI Rx DMA transfert complete callback */
1042 hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
1043
1044 /* Set the DMA error callback */
1045 hsai->hdmarx->XferErrorCallback = SAI_DMAError;
1046
1047 /* Enable the Rx DMA Stream */
1048 tmp = (uint32_t*)&pData;
1049 HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, *(uint32_t*)tmp, hsai->RxXferSize);
1050
1051 /* Check if the SAI is already enabled */
1052 if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
1053 {
1054 /* Enable SAI peripheral */
1055 __HAL_SAI_ENABLE(hsai);
1056 }
1057
1058 /* Enable SAI Rx DMA Request */
1059 hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
1060
1061 /* Process Unlocked */
1062 __HAL_UNLOCK(hsai);
1063
1064 return HAL_OK;
1065 }
1066 else
1067 {
1068 return HAL_BUSY;
1069 }
1070 }
1071
1072 /**
1073 * @brief This function handles SAI interrupt request.
1074 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1075 * the configuration information for SAI module.
1076 * @retval HAL status
1077 */
1078 void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
1079 {
1080 uint32_t tmp1 = 0, tmp2 = 0;
1081
1082 if(hsai->State == HAL_SAI_STATE_BUSY_RX)
1083 {
1084 tmp1 = __HAL_SAI_GET_FLAG(hsai, SAI_xSR_FREQ);
1085 tmp2 = __HAL_SAI_GET_IT_SOURCE(hsai, SAI_IT_FREQ);
1086 /* SAI in mode Receiver --------------------------------------------------*/
1087 if((tmp1 != RESET) && (tmp2 != RESET))
1088 {
1089 HAL_SAI_Receive_IT(hsai, HAL_NULL, 0);
1090 }
1091
1092 tmp1 = __HAL_SAI_GET_FLAG(hsai, SAI_FLAG_OVRUDR);
1093 tmp2 = __HAL_SAI_GET_IT_SOURCE(hsai, SAI_IT_OVRUDR);
1094 /* SAI Overrun error interrupt occurred ----------------------------------*/
1095 if((tmp1 != RESET) && (tmp2 != RESET))
1096 {
1097 /* Change the SAI error code */
1098 hsai->ErrorCode = HAL_SAI_ERROR_OVR;
1099
1100 /* Clear the SAI Overrun flag */
1101 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1102 /* Set the SAI state ready to be able to start again the process */
1103 hsai->State = HAL_SAI_STATE_READY;
1104 HAL_SAI_ErrorCallback(hsai);
1105 }
1106 }
1107
1108 if(hsai->State == HAL_SAI_STATE_BUSY_TX)
1109 {
1110 tmp1 = __HAL_SAI_GET_FLAG(hsai, SAI_xSR_FREQ);
1111 tmp2 = __HAL_SAI_GET_IT_SOURCE(hsai, SAI_IT_FREQ);
1112 /* SAI in mode Transmitter -----------------------------------------------*/
1113 if((tmp1 != RESET) && (tmp2 != RESET))
1114 {
1115 HAL_SAI_Transmit_IT(hsai, HAL_NULL, 0);
1116 }
1117
1118 tmp1 = __HAL_SAI_GET_FLAG(hsai, SAI_FLAG_OVRUDR);
1119 tmp2 = __HAL_SAI_GET_IT_SOURCE(hsai, SAI_IT_OVRUDR);
1120 /* SAI Underrun error interrupt occurred ---------------------------------*/
1121 if((tmp1 != RESET) && (tmp2 != RESET))
1122 {
1123 /* Change the SAI error code */
1124 hsai->ErrorCode = HAL_SAI_ERROR_UDR;
1125
1126 /* Clear the SAI Underrun flag */
1127 __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
1128 /* Set the SAI state ready to be able to start again the process */
1129 hsai->State = HAL_SAI_STATE_READY;
1130 HAL_SAI_ErrorCallback(hsai);
1131 }
1132 }
1133 }
1134
1135 /**
1136 * @brief Tx Transfer completed callbacks.
1137 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1138 * the configuration information for SAI module.
1139 * @retval None
1140 */
1141 __weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
1142 {
1143 /* NOTE : This function Should not be modified, when the callback is needed,
1144 the HAL_SAI_TxCpltCallback could be implemented in the user file
1145 */
1146 }
1147
1148 /**
1149 * @brief Tx Transfer Half completed callbacks
1150 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1151 * the configuration information for SAI module.
1152 * @retval None
1153 */
1154 __weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1155 {
1156 /* NOTE : This function Should not be modified, when the callback is needed,
1157 the HAL_SAI_TxHalfCpltCallback could be implenetd in the user file
1158 */
1159 }
1160
1161 /**
1162 * @brief Rx Transfer completed callbacks.
1163 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1164 * the configuration information for SAI module.
1165 * @retval None
1166 */
1167 __weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
1168 {
1169 /* NOTE : This function Should not be modified, when the callback is needed,
1170 the HAL_SAI_RxCpltCallback could be implemented in the user file
1171 */
1172 }
1173
1174 /**
1175 * @brief Rx Transfer half completed callbacks
1176 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1177 * the configuration information for SAI module.
1178 * @retval None
1179 */
1180 __weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
1181 {
1182 /* NOTE : This function Should not be modified, when the callback is needed,
1183 the HAL_SAI_RxCpltCallback could be implenetd in the user file
1184 */
1185 }
1186
1187 /**
1188 * @brief SAI error callbacks.
1189 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1190 * the configuration information for SAI module.
1191 * @retval None
1192 */
1193 __weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
1194 {
1195 /* NOTE : This function Should not be modified, when the callback is needed,
1196 the HAL_SAI_ErrorCallback could be implemented in the user file
1197 */
1198 }
1199
1200 /**
1201 * @}
1202 */
1203
1204
1205 /** @defgroup SAI_Group3 Peripheral State functions
1206 * @brief Peripheral State functions
1207 *
1208 @verbatim
1209 ===============================================================================
1210 ##### Peripheral State and Errors functions #####
1211 ===============================================================================
1212 [..]
1213 This subsection permits to get in run-time the status of the peripheral
1214 and the data flow.
1215
1216 @endverbatim
1217 * @{
1218 */
1219
1220 /**
1221 * @brief Returns the SAI state.
1222 * @param hsai: pointer to a SAI_HandleTypeDef structure that contains
1223 * the configuration information for SAI module.
1224 * @retval HAL state
1225 */
1226 HAL_SAI_StateTypeDef HAL_SAI_GetState(SAI_HandleTypeDef *hsai)
1227 {
1228 return hsai->State;
1229 }
1230
1231 /**
1232 * @brief Return the SAI error code
1233 * @param hsai : pointer to a SAI_HandleTypeDef structure that contains
1234 * the configuration information for the specified SAI Block.
1235 * @retval SAI Error Code
1236 */
1237 uint32_t HAL_SAI_GetError(SAI_HandleTypeDef *hsai)
1238 {
1239 return hsai->ErrorCode;
1240 }
1241 /**
1242 * @}
1243 */
1244
1245 /**
1246 * @brief DMA SAI transmit process complete callback.
1247 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1248 * the configuration information for the specified DMA module.
1249 * @retval None
1250 */
1251 static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
1252 {
1253 uint32_t tickstart = 0;
1254
1255 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef* )hdma)->Parent;
1256
1257 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
1258 {
1259 hsai->TxXferCount = 0;
1260 hsai->RxXferCount = 0;
1261
1262 /* Disable SAI Tx DMA Request */
1263 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
1264
1265 /* Get tick */
1266 tickstart = HAL_GetTick();
1267
1268 /* Set timeout: 10 is the max delay to send the remaining data in the SAI FIFO */
1269 /* Wait until FIFO is empty */
1270 while(__HAL_SAI_GET_FLAG(hsai, SAI_xSR_FLVL) != RESET)
1271 {
1272 /* Check for the Timeout */
1273 if((HAL_GetTick() - tickstart ) > SAI_TIMEOUT_VALUE)
1274 {
1275 /* Update error code */
1276 hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
1277
1278 /* Change the SAI state */
1279 HAL_SAI_ErrorCallback(hsai);
1280 }
1281 }
1282
1283 hsai->State= HAL_SAI_STATE_READY;
1284 }
1285 HAL_SAI_TxCpltCallback(hsai);
1286 }
1287
1288 /**
1289 * @brief DMA SAI transmit process half complete callback
1290 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1291 * the configuration information for the specified DMA module.
1292 * @retval None
1293 */
1294 static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
1295 {
1296 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
1297
1298 HAL_SAI_TxHalfCpltCallback(hsai);
1299 }
1300
1301 /**
1302 * @brief DMA SAI receive process complete callback.
1303 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1304 * the configuration information for the specified DMA module.
1305 * @retval None
1306 */
1307 static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
1308 {
1309 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1310 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
1311 {
1312 /* Disable Rx DMA Request */
1313 hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
1314 hsai->RxXferCount = 0;
1315
1316 hsai->State = HAL_SAI_STATE_READY;
1317 }
1318 HAL_SAI_RxCpltCallback(hsai);
1319 }
1320
1321 /**
1322 * @brief DMA SAI receive process half complete callback
1323 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1324 * the configuration information for the specified DMA module.
1325 * @retval None
1326 */
1327 static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
1328 {
1329 SAI_HandleTypeDef* hsai = (SAI_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
1330
1331 HAL_SAI_RxHalfCpltCallback(hsai);
1332 }
1333 /**
1334 * @brief DMA SAI communication error callback.
1335 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1336 * the configuration information for the specified DMA module.
1337 * @retval None
1338 */
1339 static void SAI_DMAError(DMA_HandleTypeDef *hdma)
1340 {
1341 SAI_HandleTypeDef* hsai = ( SAI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1342 /* Set the SAI state ready to be able to start again the process */
1343 hsai->State= HAL_SAI_STATE_READY;
1344 HAL_SAI_ErrorCallback(hsai);
1345
1346 hsai->TxXferCount = 0;
1347 hsai->RxXferCount = 0;
1348 }
1349
1350 /**
1351 * @}
1352 */
1353
1354 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
1355 #endif /* HAL_SAI_MODULE_ENABLED */
1356 /**
1357 * @}
1358 */
1359
1360 /**
1361 * @}
1362 */
1363
1364 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Imprint / Impressum