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