Mercurial > public > ostc4
comparison Common/Drivers/STM32F4xx_HAL_DRIVER_v120/Src/stm32f4xx_hal_i2s_ex.c @ 38:5f11787b4f42
include in ostc4 repository
author | heinrichsweikamp |
---|---|
date | Sat, 28 Apr 2018 11:52:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
37:ccc45c0e1ea2 | 38:5f11787b4f42 |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file stm32f4xx_hal_i2s_ex.c | |
4 * @author MCD Application Team | |
5 * @version V1.2.0 | |
6 * @date 26-December-2014 | |
7 * @brief I2S HAL module driver. | |
8 * This file provides firmware functions to manage the following | |
9 * functionalities of I2S extension peripheral: | |
10 * + Extension features Functions | |
11 * | |
12 @verbatim | |
13 ============================================================================== | |
14 ##### I2S Extension features ##### | |
15 ============================================================================== | |
16 [..] | |
17 (#) In I2S full duplex mode, each SPI peripheral is able to manage sending and receiving | |
18 data simultaneously using two data lines. Each SPI peripheral has an extended block | |
19 called I2Sxext (i.e I2S2ext for SPI2 and I2S3ext for SPI3). | |
20 (#) The extension block is not a full SPI IP, it is used only as I2S slave to | |
21 implement full duplex mode. The extension block uses the same clock sources | |
22 as its master. | |
23 | |
24 (#) Both I2Sx and I2Sx_ext can be configured as transmitters or receivers. | |
25 | |
26 [..] | |
27 (@) Only I2Sx can deliver SCK and WS to I2Sx_ext in full duplex mode, where | |
28 I2Sx can be I2S2 or I2S3. | |
29 | |
30 ##### How to use this driver ##### | |
31 =============================================================================== | |
32 [..] | |
33 Three operation modes are available within this driver : | |
34 | |
35 *** Polling mode IO operation *** | |
36 ================================= | |
37 [..] | |
38 (+) Send and receive in the same time an amount of data in blocking mode using HAL_I2S_TransmitReceive() | |
39 | |
40 *** Interrupt mode IO operation *** | |
41 =================================== | |
42 [..] | |
43 (+) Send and receive in the same time an amount of data in non blocking mode using HAL_I2S_TransmitReceive_IT() | |
44 (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can | |
45 add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback | |
46 (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can | |
47 add his own code by customization of function pointer HAL_I2S_TxCpltCallback | |
48 (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can | |
49 add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback | |
50 (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can | |
51 add his own code by customization of function pointer HAL_I2S_RxCpltCallback | |
52 (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can | |
53 add his own code by customization of function pointer HAL_I2S_ErrorCallback | |
54 | |
55 *** DMA mode IO operation *** | |
56 ============================== | |
57 [..] | |
58 (+) Send and receive an amount of data in non blocking mode (DMA) using HAL_I2S_TransmitReceive_DMA() | |
59 (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can | |
60 add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback | |
61 (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can | |
62 add his own code by customization of function pointer HAL_I2S_TxCpltCallback | |
63 (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can | |
64 add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback | |
65 (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can | |
66 add his own code by customization of function pointer HAL_I2S_RxCpltCallback | |
67 (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can | |
68 add his own code by customization of function pointer HAL_I2S_ErrorCallback | |
69 (+) Pause the DMA Transfer using HAL_I2S_DMAPause() | |
70 (+) Resume the DMA Transfer using HAL_I2S_DMAResume() | |
71 (+) Stop the DMA Transfer using HAL_I2S_DMAStop() | |
72 | |
73 @endverbatim | |
74 ****************************************************************************** | |
75 * @attention | |
76 * | |
77 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> | |
78 * | |
79 * Redistribution and use in source and binary forms, with or without modification, | |
80 * are permitted provided that the following conditions are met: | |
81 * 1. Redistributions of source code must retain the above copyright notice, | |
82 * this list of conditions and the following disclaimer. | |
83 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
84 * this list of conditions and the following disclaimer in the documentation | |
85 * and/or other materials provided with the distribution. | |
86 * 3. Neither the name of STMicroelectronics nor the names of its contributors | |
87 * may be used to endorse or promote products derived from this software | |
88 * without specific prior written permission. | |
89 * | |
90 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
91 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
92 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
93 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
94 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
95 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
96 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
97 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
98 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
99 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
100 * | |
101 ****************************************************************************** | |
102 */ | |
103 | |
104 /* Includes ------------------------------------------------------------------*/ | |
105 #include "stm32f4xx_hal.h" | |
106 | |
107 /** @addtogroup STM32F4xx_HAL_Driver | |
108 * @{ | |
109 */ | |
110 | |
111 /** @defgroup I2SEx I2SEx | |
112 * @brief I2S HAL module driver | |
113 * @{ | |
114 */ | |
115 | |
116 #ifdef HAL_I2S_MODULE_ENABLED | |
117 | |
118 /* Private typedef -----------------------------------------------------------*/ | |
119 /* Private define ------------------------------------------------------------*/ | |
120 /* Private macro -------------------------------------------------------------*/ | |
121 /* Private variables ---------------------------------------------------------*/ | |
122 /* Private function prototypes -----------------------------------------------*/ | |
123 /* Private functions ---------------------------------------------------------*/ | |
124 /** @addtogroup I2SEx_Private_Functions | |
125 * @{ | |
126 */ | |
127 /** | |
128 * @} | |
129 */ | |
130 | |
131 /* Exported functions --------------------------------------------------------*/ | |
132 /** @defgroup I2SEx_Exported_Functions I2S Exported Functions | |
133 * @{ | |
134 */ | |
135 | |
136 /** @defgroup I2SEx_Group1 Extension features functions | |
137 * @brief Extension features functions | |
138 * | |
139 @verbatim | |
140 =============================================================================== | |
141 ##### Extension features Functions ##### | |
142 =============================================================================== | |
143 [..] | |
144 This subsection provides a set of functions allowing to manage the I2S data | |
145 transfers. | |
146 | |
147 (#) There are two modes of transfer: | |
148 (++) Blocking mode : The communication is performed in the polling mode. | |
149 The status of all data processing is returned by the same function | |
150 after finishing transfer. | |
151 (++) No-Blocking mode : The communication is performed using Interrupts | |
152 or DMA. These functions return the status of the transfer startup. | |
153 The end of the data processing will be indicated through the | |
154 dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when | |
155 using DMA mode. | |
156 | |
157 (#) Blocking mode functions are : | |
158 (++) HAL_I2S_TransmitReceive() | |
159 | |
160 (#) No-Blocking mode functions with Interrupt are : | |
161 (++) HAL_I2S_TransmitReceive_IT() | |
162 | |
163 (#) No-Blocking mode functions with DMA are : | |
164 (++) HAL_I2S_TransmitReceive_DMA() | |
165 | |
166 (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: | |
167 (++) HAL_I2S_TxCpltCallback() | |
168 (++) HAL_I2S_RxCpltCallback() | |
169 (++) HAL_I2S_ErrorCallback() | |
170 | |
171 @endverbatim | |
172 * @{ | |
173 */ | |
174 | |
175 /** | |
176 * @brief Full-Duplex Transmit/Receive data in blocking mode. | |
177 * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains | |
178 * the configuration information for I2S module | |
179 * @param pTxData: a 16-bit pointer to the Transmit data buffer. | |
180 * @param pRxData: a 16-bit pointer to the Receive data buffer. | |
181 * @param Size: number of data sample to be sent: | |
182 * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S | |
183 * configuration phase, the Size parameter means the number of 16-bit data length | |
184 * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected | |
185 * the Size parameter means the number of 16-bit data length. | |
186 * @param Timeout: Timeout duration | |
187 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization | |
188 * between Master and Slave(example: audio streaming). | |
189 * @retval HAL status | |
190 */ | |
191 HAL_StatusTypeDef HAL_I2SEx_TransmitReceive(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size, uint32_t Timeout) | |
192 { | |
193 uint32_t tickstart = 0; | |
194 uint32_t tmp1 = 0, tmp2 = 0; | |
195 | |
196 if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) | |
197 { | |
198 return HAL_ERROR; | |
199 } | |
200 | |
201 /* Check the I2S State */ | |
202 if(hi2s->State == HAL_I2S_STATE_READY) | |
203 { | |
204 tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
205 tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
206 /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended | |
207 is selected during the I2S configuration phase, the Size parameter means the number | |
208 of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data | |
209 frame is selected the Size parameter means the number of 16-bit data length. */ | |
210 if((tmp1 == I2S_DATAFORMAT_24B)|| \ | |
211 (tmp2 == I2S_DATAFORMAT_32B)) | |
212 { | |
213 hi2s->TxXferSize = Size*2; | |
214 hi2s->TxXferCount = Size*2; | |
215 hi2s->RxXferSize = Size*2; | |
216 hi2s->RxXferCount = Size*2; | |
217 } | |
218 else | |
219 { | |
220 hi2s->TxXferSize = Size; | |
221 hi2s->TxXferCount = Size; | |
222 hi2s->RxXferSize = Size; | |
223 hi2s->RxXferCount = Size; | |
224 } | |
225 | |
226 /* Process Locked */ | |
227 __HAL_LOCK(hi2s); | |
228 | |
229 /* Set the I2S State busy TX/RX */ | |
230 hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; | |
231 | |
232 tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
233 tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
234 /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ | |
235 if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) | |
236 { | |
237 /* Check if the I2S is already enabled: The I2S is kept enabled at the end of transaction | |
238 to avoid the clock de-synchronization between Master and Slave. */ | |
239 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
240 { | |
241 /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ | |
242 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
243 | |
244 /* Enable I2Sx peripheral */ | |
245 __HAL_I2S_ENABLE(hi2s); | |
246 } | |
247 | |
248 while(hi2s->TxXferCount > 0) | |
249 { | |
250 /* Wait until TXE flag is set */ | |
251 if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, RESET, Timeout) != HAL_OK) | |
252 { | |
253 return HAL_TIMEOUT; | |
254 } | |
255 hi2s->Instance->DR = (*pTxData++); | |
256 | |
257 /* Get tick */ | |
258 tickstart = HAL_GetTick(); | |
259 | |
260 /* Wait until RXNE flag is set */ | |
261 while((I2SxEXT(hi2s->Instance)->SR & SPI_SR_RXNE) != SPI_SR_RXNE) | |
262 { | |
263 if(Timeout != HAL_MAX_DELAY) | |
264 { | |
265 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) | |
266 { | |
267 /* Process Unlocked */ | |
268 __HAL_UNLOCK(hi2s); | |
269 | |
270 return HAL_TIMEOUT; | |
271 } | |
272 } | |
273 } | |
274 (*pRxData++) = I2SxEXT(hi2s->Instance)->DR; | |
275 | |
276 hi2s->TxXferCount--; | |
277 hi2s->RxXferCount--; | |
278 } | |
279 } | |
280 /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ | |
281 else | |
282 { | |
283 /* Check if the I2S is already enabled */ | |
284 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
285 { | |
286 /* Enable I2S peripheral before the I2Sext*/ | |
287 __HAL_I2S_ENABLE(hi2s); | |
288 | |
289 /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ | |
290 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
291 } | |
292 else | |
293 { | |
294 /* Check if Master Receiver mode is selected */ | |
295 if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) | |
296 { | |
297 /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read | |
298 access to the SPI_SR register. */ | |
299 __HAL_I2S_CLEAR_OVRFLAG(hi2s); | |
300 } | |
301 } | |
302 while(hi2s->TxXferCount > 0) | |
303 { | |
304 /* Get tick */ | |
305 tickstart = HAL_GetTick(); | |
306 | |
307 /* Wait until TXE flag is set */ | |
308 while((I2SxEXT(hi2s->Instance)->SR & SPI_SR_TXE) != SPI_SR_TXE) | |
309 { | |
310 if(Timeout != HAL_MAX_DELAY) | |
311 { | |
312 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) | |
313 { | |
314 /* Process Unlocked */ | |
315 __HAL_UNLOCK(hi2s); | |
316 | |
317 return HAL_TIMEOUT; | |
318 } | |
319 } | |
320 } | |
321 I2SxEXT(hi2s->Instance)->DR = (*pTxData++); | |
322 | |
323 /* Wait until RXNE flag is set */ | |
324 if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, RESET, Timeout) != HAL_OK) | |
325 { | |
326 return HAL_TIMEOUT; | |
327 } | |
328 (*pRxData++) = hi2s->Instance->DR; | |
329 | |
330 hi2s->TxXferCount--; | |
331 hi2s->RxXferCount--; | |
332 } | |
333 } | |
334 | |
335 /* Set the I2S State ready */ | |
336 hi2s->State = HAL_I2S_STATE_READY; | |
337 | |
338 /* Process Unlocked */ | |
339 __HAL_UNLOCK(hi2s); | |
340 | |
341 return HAL_OK; | |
342 } | |
343 else | |
344 { | |
345 return HAL_BUSY; | |
346 } | |
347 } | |
348 | |
349 /** | |
350 * @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt | |
351 * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains | |
352 * the configuration information for I2S module | |
353 * @param pTxData: a 16-bit pointer to the Transmit data buffer. | |
354 * @param pRxData: a 16-bit pointer to the Receive data buffer. | |
355 * @param Size: number of data sample to be sent: | |
356 * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S | |
357 * configuration phase, the Size parameter means the number of 16-bit data length | |
358 * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected | |
359 * the Size parameter means the number of 16-bit data length. | |
360 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization | |
361 * between Master and Slave(example: audio streaming). | |
362 * @retval HAL status | |
363 */ | |
364 HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size) | |
365 { | |
366 uint32_t tmp1 = 0, tmp2 = 0; | |
367 | |
368 if(hi2s->State == HAL_I2S_STATE_READY) | |
369 { | |
370 if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) | |
371 { | |
372 return HAL_ERROR; | |
373 } | |
374 | |
375 hi2s->pTxBuffPtr = pTxData; | |
376 hi2s->pRxBuffPtr = pRxData; | |
377 | |
378 tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
379 tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
380 /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended | |
381 is selected during the I2S configuration phase, the Size parameter means the number | |
382 of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data | |
383 frame is selected the Size parameter means the number of 16-bit data length. */ | |
384 if((tmp1 == I2S_DATAFORMAT_24B)||\ | |
385 (tmp2 == I2S_DATAFORMAT_32B)) | |
386 { | |
387 hi2s->TxXferSize = Size*2; | |
388 hi2s->TxXferCount = Size*2; | |
389 hi2s->RxXferSize = Size*2; | |
390 hi2s->RxXferCount = Size*2; | |
391 } | |
392 else | |
393 { | |
394 hi2s->TxXferSize = Size; | |
395 hi2s->TxXferCount = Size; | |
396 hi2s->RxXferSize = Size; | |
397 hi2s->RxXferCount = Size; | |
398 } | |
399 | |
400 /* Process Locked */ | |
401 __HAL_LOCK(hi2s); | |
402 | |
403 hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; | |
404 hi2s->ErrorCode = HAL_I2S_ERROR_NONE; | |
405 | |
406 tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
407 tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
408 /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ | |
409 if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) | |
410 { | |
411 /* Enable I2Sext RXNE and ERR interrupts */ | |
412 I2SxEXT(hi2s->Instance)->CR2 |= (I2S_IT_RXNE | I2S_IT_ERR); | |
413 | |
414 /* Enable I2Sx TXE and ERR interrupts */ | |
415 __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); | |
416 | |
417 /* Check if the I2S is already enabled */ | |
418 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
419 { | |
420 /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ | |
421 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
422 | |
423 /* Enable I2Sx peripheral */ | |
424 __HAL_I2S_ENABLE(hi2s); | |
425 } | |
426 } | |
427 /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ | |
428 else | |
429 { | |
430 /* Enable I2Sext TXE and ERR interrupts */ | |
431 I2SxEXT(hi2s->Instance)->CR2 |= (I2S_IT_TXE |I2S_IT_ERR); | |
432 | |
433 /* Enable I2Sext RXNE and ERR interrupts */ | |
434 __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); | |
435 | |
436 /* Check if the I2S is already enabled */ | |
437 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
438 { | |
439 /* Check if the I2S_MODE_MASTER_RX is selected */ | |
440 if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) | |
441 { | |
442 /* Prepare the First Data before enabling the I2S */ | |
443 if(hi2s->TxXferCount != 0) | |
444 { | |
445 /* Transmit First data */ | |
446 I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); | |
447 hi2s->TxXferCount--; | |
448 | |
449 if(hi2s->TxXferCount == 0) | |
450 { | |
451 /* Disable I2Sext TXE interrupt */ | |
452 I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_TXE; | |
453 } | |
454 } | |
455 } | |
456 /* Enable I2S peripheral */ | |
457 __HAL_I2S_ENABLE(hi2s); | |
458 | |
459 /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ | |
460 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
461 } | |
462 } | |
463 /* Process Unlocked */ | |
464 __HAL_UNLOCK(hi2s); | |
465 | |
466 return HAL_OK; | |
467 } | |
468 else | |
469 { | |
470 return HAL_BUSY; | |
471 } | |
472 } | |
473 | |
474 /** | |
475 * @brief Full-Duplex Transmit/Receive data in non-blocking mode using DMA | |
476 * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains | |
477 * the configuration information for I2S module | |
478 * @param pTxData: a 16-bit pointer to the Transmit data buffer. | |
479 * @param pRxData: a 16-bit pointer to the Receive data buffer. | |
480 * @param Size: number of data sample to be sent: | |
481 * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S | |
482 * configuration phase, the Size parameter means the number of 16-bit data length | |
483 * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected | |
484 * the Size parameter means the number of 16-bit data length. | |
485 * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization | |
486 * between Master and Slave(example: audio streaming). | |
487 * @retval HAL status | |
488 */ | |
489 HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, uint16_t Size) | |
490 { | |
491 uint32_t *tmp; | |
492 uint32_t tmp1 = 0, tmp2 = 0; | |
493 | |
494 if((pTxData == NULL ) || (pRxData == NULL ) || (Size == 0)) | |
495 { | |
496 return HAL_ERROR; | |
497 } | |
498 | |
499 if(hi2s->State == HAL_I2S_STATE_READY) | |
500 { | |
501 hi2s->pTxBuffPtr = pTxData; | |
502 hi2s->pRxBuffPtr = pRxData; | |
503 | |
504 tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
505 tmp2 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); | |
506 /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended | |
507 is selected during the I2S configuration phase, the Size parameter means the number | |
508 of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data | |
509 frame is selected the Size parameter means the number of 16-bit data length. */ | |
510 if((tmp1 == I2S_DATAFORMAT_24B)||\ | |
511 (tmp2 == I2S_DATAFORMAT_32B)) | |
512 { | |
513 hi2s->TxXferSize = Size*2; | |
514 hi2s->TxXferCount = Size*2; | |
515 hi2s->RxXferSize = Size*2; | |
516 hi2s->RxXferCount = Size*2; | |
517 } | |
518 else | |
519 { | |
520 hi2s->TxXferSize = Size; | |
521 hi2s->TxXferCount = Size; | |
522 hi2s->RxXferSize = Size; | |
523 hi2s->RxXferCount = Size; | |
524 } | |
525 | |
526 /* Process Locked */ | |
527 __HAL_LOCK(hi2s); | |
528 | |
529 hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; | |
530 hi2s->ErrorCode = HAL_I2S_ERROR_NONE; | |
531 | |
532 /* Set the I2S Rx DMA Half transfer complete callback */ | |
533 hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt; | |
534 | |
535 /* Set the I2S Rx DMA transfer complete callback */ | |
536 hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt; | |
537 | |
538 /* Set the I2S Rx DMA error callback */ | |
539 hi2s->hdmarx->XferErrorCallback = I2S_DMAError; | |
540 | |
541 /* Set the I2S Tx DMA Half transfer complete callback */ | |
542 hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt; | |
543 | |
544 /* Set the I2S Tx DMA transfer complete callback */ | |
545 hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt; | |
546 | |
547 /* Set the I2S Tx DMA error callback */ | |
548 hi2s->hdmatx->XferErrorCallback = I2S_DMAError; | |
549 | |
550 tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
551 tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
552 /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ | |
553 if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) | |
554 { | |
555 /* Enable the Rx DMA Stream */ | |
556 tmp = (uint32_t*)&pRxData; | |
557 HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, *(uint32_t*)tmp, hi2s->RxXferSize); | |
558 | |
559 /* Enable Rx DMA Request */ | |
560 I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_RXDMAEN; | |
561 | |
562 /* Enable the Tx DMA Stream */ | |
563 tmp = (uint32_t*)&pTxData; | |
564 HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize); | |
565 | |
566 /* Enable Tx DMA Request */ | |
567 hi2s->Instance->CR2 |= SPI_CR2_TXDMAEN; | |
568 | |
569 /* Check if the I2S is already enabled */ | |
570 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
571 { | |
572 /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ | |
573 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
574 | |
575 /* Enable I2S peripheral after the I2Sext */ | |
576 __HAL_I2S_ENABLE(hi2s); | |
577 } | |
578 } | |
579 else | |
580 { | |
581 /* Enable the Tx DMA Stream */ | |
582 tmp = (uint32_t*)&pTxData; | |
583 HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t*)tmp, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, hi2s->TxXferSize); | |
584 | |
585 /* Enable Tx DMA Request */ | |
586 I2SxEXT(hi2s->Instance)->CR2 |= SPI_CR2_TXDMAEN; | |
587 | |
588 /* Enable the Rx DMA Stream */ | |
589 tmp = (uint32_t*)&pRxData; | |
590 HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t*)tmp, hi2s->RxXferSize); | |
591 | |
592 /* Enable Rx DMA Request */ | |
593 hi2s->Instance->CR2 |= SPI_CR2_RXDMAEN; | |
594 | |
595 /* Check if the I2S is already enabled */ | |
596 if((hi2s->Instance->I2SCFGR &SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) | |
597 { | |
598 /* Enable I2S peripheral before the I2Sext */ | |
599 __HAL_I2S_ENABLE(hi2s); | |
600 | |
601 /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ | |
602 I2SxEXT(hi2s->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE; | |
603 } | |
604 else | |
605 { | |
606 /* Check if Master Receiver mode is selected */ | |
607 if((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) | |
608 { | |
609 /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read | |
610 access to the SPI_SR register. */ | |
611 __HAL_I2S_CLEAR_OVRFLAG(hi2s); | |
612 } | |
613 } | |
614 } | |
615 | |
616 /* Process Unlocked */ | |
617 __HAL_UNLOCK(hi2s); | |
618 | |
619 return HAL_OK; | |
620 } | |
621 else | |
622 { | |
623 return HAL_BUSY; | |
624 } | |
625 } | |
626 | |
627 /** | |
628 * @} | |
629 */ | |
630 | |
631 | |
632 /** | |
633 * @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt | |
634 * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains | |
635 * the configuration information for I2S module | |
636 * @retval HAL status | |
637 */ | |
638 HAL_StatusTypeDef I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s) | |
639 { | |
640 uint32_t tmp1 = 0, tmp2 = 0; | |
641 | |
642 if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) | |
643 { | |
644 /* Process Locked */ | |
645 __HAL_LOCK(hi2s); | |
646 | |
647 tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
648 tmp2 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; | |
649 /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ | |
650 if((tmp1 == I2S_MODE_MASTER_TX) || (tmp2 == I2S_MODE_SLAVE_TX)) | |
651 { | |
652 if(hi2s->TxXferCount != 0) | |
653 { | |
654 if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE) != RESET) | |
655 { | |
656 /* Transmit data */ | |
657 hi2s->Instance->DR = (*hi2s->pTxBuffPtr++); | |
658 hi2s->TxXferCount--; | |
659 | |
660 if(hi2s->TxXferCount == 0) | |
661 { | |
662 /* Disable TXE interrupt */ | |
663 __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_TXE); | |
664 } | |
665 } | |
666 } | |
667 | |
668 if(hi2s->RxXferCount != 0) | |
669 { | |
670 if((I2SxEXT(hi2s->Instance)->SR & SPI_SR_RXNE) == SPI_SR_RXNE) | |
671 { | |
672 /* Receive data */ | |
673 (*hi2s->pRxBuffPtr++) = I2SxEXT(hi2s->Instance)->DR; | |
674 hi2s->RxXferCount--; | |
675 | |
676 if(hi2s->RxXferCount == 0) | |
677 { | |
678 /* Disable I2Sext RXNE interrupt */ | |
679 I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_RXNE; | |
680 } | |
681 } | |
682 } | |
683 } | |
684 /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ | |
685 else | |
686 { | |
687 if(hi2s->TxXferCount != 0) | |
688 { | |
689 if((I2SxEXT(hi2s->Instance)->SR & SPI_SR_TXE) == SPI_SR_TXE) | |
690 { | |
691 /* Transmit data */ | |
692 I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); | |
693 hi2s->TxXferCount--; | |
694 | |
695 if(hi2s->TxXferCount == 0) | |
696 { | |
697 /* Disable I2Sext TXE interrupt */ | |
698 I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_TXE; | |
699 | |
700 HAL_I2S_TxCpltCallback(hi2s); | |
701 } | |
702 } | |
703 } | |
704 if(hi2s->RxXferCount != 0) | |
705 { | |
706 if(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_RXNE) != RESET) | |
707 { | |
708 /* Receive data */ | |
709 (*hi2s->pRxBuffPtr++) = hi2s->Instance->DR; | |
710 hi2s->RxXferCount--; | |
711 | |
712 if(hi2s->RxXferCount == 0) | |
713 { | |
714 /* Disable RXNE interrupt */ | |
715 __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_RXNE); | |
716 | |
717 HAL_I2S_RxCpltCallback(hi2s); | |
718 } | |
719 } | |
720 } | |
721 } | |
722 | |
723 tmp1 = hi2s->RxXferCount; | |
724 tmp2 = hi2s->TxXferCount; | |
725 if((tmp1 == 0) && (tmp2 == 0)) | |
726 { | |
727 /* Disable I2Sx ERR interrupt */ | |
728 __HAL_I2S_DISABLE_IT(hi2s, I2S_IT_ERR); | |
729 /* Disable I2Sext ERR interrupt */ | |
730 I2SxEXT(hi2s->Instance)->CR2 &= ~I2S_IT_ERR; | |
731 | |
732 hi2s->State = HAL_I2S_STATE_READY; | |
733 } | |
734 | |
735 /* Process Unlocked */ | |
736 __HAL_UNLOCK(hi2s); | |
737 | |
738 return HAL_OK; | |
739 } | |
740 else | |
741 { | |
742 return HAL_BUSY; | |
743 } | |
744 } | |
745 | |
746 /** | |
747 * @} | |
748 */ | |
749 | |
750 #endif /* HAL_I2S_MODULE_ENABLED */ | |
751 /** | |
752 * @} | |
753 */ | |
754 | |
755 /** | |
756 * @} | |
757 */ | |
758 | |
759 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |