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