]> git.donarmstrong.com Git - qmk_firmware.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
[qmk_firmware.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****/