1 /*!
2 * @file apm32f4xx_spi.c
3 *
4 * @brief This file provides all the SPI firmware functions
5 *
6 * @version V1.0.2
7 *
8 * @date 2022-06-23
9 *
10 * @attention
11 *
12 * Copyright (C) 2021-2022 Geehy Semiconductor
13 *
14 * You may not use this file except in compliance with the
15 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16 *
17 * The program is only for reference, which is distributed in the hope
18 * that it will be usefull and instructional for customers to develop
19 * their software. Unless required by applicable law or agreed to in
20 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23 * and limitations under the License.
24 */
25
26 #include "apm32f4xx_spi.h"
27 #include "apm32f4xx_rcm.h"
28
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30 @{
31 */
32
33 /** @defgroup SPI_Driver
34 * @brief SPI driver modules
35 @{
36 */
37
38 /** @defgroup SPI_Functions
39 @{
40 */
41
42 /*!
43 * @brief Reset the specified SPIx peripheral
44 *
45 * @param spi: The SPIx can be 1,2,3,4,5,6
46 *
47 * @retval None
48 */
SPI_I2S_Reset(SPI_T * spi)49 void SPI_I2S_Reset(SPI_T *spi)
50 {
51 if (spi == SPI1)
52 {
53 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
54 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
55 }
56 else if (spi == SPI2)
57 {
58 RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2);
59 RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_SPI2);
60 }
61 else if (spi == SPI3)
62 {
63 RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_SPI3);
64 RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_SPI3);
65 }
66 else if (spi == SPI4)
67 {
68 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI4);
69 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI4);
70 }
71 else if (spi == SPI5)
72 {
73 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI5);
74 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI5);
75 }
76 else if (spi == SPI6)
77 {
78 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI6);
79 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI6);
80 }
81 }
82
83 /*!
84 * @brief Config the SPI peripheral according to the specified parameters in the spiConfig
85 *
86 * @param spi: The SPIx can be 1,2,3,4,5,6.
87 *
88 * @param spiConfig: pointer to a SPI_Config_T structure
89 *
90 * @retval None
91 */
SPI_Config(SPI_T * spi,SPI_Config_T * spiConfig)92 void SPI_Config(SPI_T *spi, SPI_Config_T *spiConfig)
93 {
94 spi->CTRL1_B.MSMCFG = spiConfig->mode;
95 spi->CTRL1_B.ISSEL = spiConfig->mode;
96 spi->CTRL1_B.DFLSEL = spiConfig->length;
97 spi->CTRL1_B.CPHA = spiConfig->phase;
98 spi->CTRL1_B.CPOL = spiConfig->polarity;
99 spi->CTRL1_B.SSEN = spiConfig->nss;
100 spi->CTRL1_B.LSBSEL = spiConfig->firstBit;
101 /** 1 line or 2 lines */
102 spi->CTRL1_B.BMEN = spiConfig->direction & 0x0001;
103 /** Tx or Rx in 1 line */
104 spi->CTRL1_B.BMOEN = (spiConfig->direction & 0x0010) >> 4;
105 /** receive only or full-duplex in 2 lines */
106 spi->CTRL1_B.RXOMEN = (spiConfig->direction & 0x0100) >> 8;
107 spi->CTRL1_B.BRSEL = spiConfig->baudrateDiv;
108
109 spi->CRCPOLY_B.CRCPOLY = spiConfig->crcPolynomial;
110 }
111
112 /*!
113 * @brief Config the I2S peripheral according to the specified parameters in the spiConfig
114 *
115 * @param spi: The SPIx can be 2,3
116 *
117 * @param i2sConfig: pointer to a I2S_Config_T structure
118 *
119 * @retval None
120 */
I2S_Config(SPI_T * spi,I2S_Config_T * i2sConfig)121 void I2S_Config(SPI_T *spi, I2S_Config_T *i2sConfig)
122 {
123 uint16_t i2sDiv = 2, i2sOdd = 0, packetSize = 1;
124 uint32_t tmp = 0;
125 uint32_t sysClock = 0;
126
127 /* Clear MODESEL, I2SEN, I2SMOD, PFSSEL, I2SSSEL, CPOL, DATALEN and CHLEN bits */
128 spi->I2SCFG &= 0xF040;
129 spi->I2SPSC = 0x0002;
130
131 if (i2sConfig->audioDiv == I2S_AUDIO_DIV_DEFAULT)
132 {
133 i2sDiv = 2;
134 i2sOdd = 0;
135 }
136 else
137 {
138 if (i2sConfig->length == I2S_DATA_LENGHT_16B)
139 {
140 packetSize = 1;
141 }
142 else
143 {
144 packetSize = 2;
145 }
146
147 sysClock = RCM_ReadSYSCLKFreq();
148
149 if (i2sConfig->MCLKOutput == I2S_MCLK_OUTPUT_ENABLE)
150 {
151 tmp = (uint16_t)(((((sysClock / 256) * 10) / i2sConfig->audioDiv)) + 5);
152 }
153 else
154 {
155 tmp = (uint16_t)(((((sysClock / (32 * packetSize)) * 10) / i2sConfig->audioDiv)) + 5);
156 }
157
158 tmp = tmp / 10;
159
160 i2sOdd = (uint16_t)(tmp & (uint16_t)0x0001);
161 i2sDiv = (uint16_t)((tmp - i2sOdd) / 2);
162
163 if ((i2sDiv < 2) || (i2sDiv > 0xFF))
164 {
165 i2sDiv = 2;
166 i2sOdd = 0;
167 }
168 }
169
170 spi->I2SPSC_B.I2SPSC = i2sDiv;
171 spi->I2SPSC_B.ODDPSC = i2sOdd;
172 spi->I2SPSC_B.MCOEN = i2sConfig->MCLKOutput;
173
174 spi->I2SCFG_B.I2SMOD = i2sConfig->mode;
175 spi->I2SCFG_B.I2SSSEL = i2sConfig->standard & 0x03;
176 spi->I2SCFG_B.PFSSEL = (i2sConfig->standard & 0x10) >> 4;
177 spi->I2SCFG_B.CHLEN = i2sConfig->length & 0x01;
178 spi->I2SCFG_B.DATLEN = i2sConfig->length >> 1;
179 spi->I2SCFG_B.CPOL = i2sConfig->polarity;
180
181 /** select I2S mode */
182 spi->I2SCFG_B.MODESEL = BIT_SET;
183 }
184
185 /*!
186 * @brief Fills each SPI_Config_T member with its default value
187 *
188 * @param spiConfig: pointer to a SPI_Config_T structure
189 *
190 * @retval None
191 */
SPI_ConfigStructInit(SPI_Config_T * spiConfig)192 void SPI_ConfigStructInit(SPI_Config_T *spiConfig)
193 {
194 spiConfig->direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
195 spiConfig->mode = SPI_MODE_SLAVE;
196 spiConfig->length = SPI_DATA_LENGTH_8B;
197 spiConfig->polarity = SPI_CLKPOL_LOW;
198 spiConfig->phase = SPI_CLKPHA_1EDGE;
199 spiConfig->nss = SPI_NSS_HARD;
200 spiConfig->baudrateDiv = SPI_BAUDRATE_DIV_2;
201 spiConfig->firstBit = SPI_FIRSTBIT_MSB;
202 spiConfig->crcPolynomial = 7;
203 }
204
205 /*!
206 * @brief Fills each I2S_Config_T member with its default value
207 *
208 * @param i2sConfig: pointer to a I2S_Config_T structure
209 *
210 * @retval None
211 */
I2S_ConfigStructInit(I2S_Config_T * i2sConfig)212 void I2S_ConfigStructInit(I2S_Config_T *i2sConfig)
213 {
214 i2sConfig->mode = I2S_MODE_SLAVE_TX;
215 i2sConfig->standard = I2S_STANDARD_PHILLIPS;
216 i2sConfig->length = I2S_DATA_LENGHT_16B;
217 i2sConfig->MCLKOutput = I2S_MCLK_OUTPUT_DISABLE;
218 i2sConfig->audioDiv = I2S_AUDIO_DIV_DEFAULT;
219 i2sConfig->polarity = I2S_CLKPOL_LOW;
220 }
221
222 /*!
223 * @brief Enables the specified SPI peripheral
224 *
225 * @param spi: The SPIx can be 1,2,3,4,5,6.
226 *
227 * @retval None
228 */
SPI_Enable(SPI_T * spi)229 void SPI_Enable(SPI_T *spi)
230 {
231 spi->CTRL1_B.SPIEN = BIT_SET;
232 }
233
234 /*!
235 * @brief Disable the specified SPI peripheral
236 *
237 * @param spi: The SPIx can be 1,2,3,4,5,6.
238 *
239 * @retval None
240 */
SPI_Disable(SPI_T * spi)241 void SPI_Disable(SPI_T *spi)
242 {
243 spi->CTRL1_B.SPIEN = BIT_RESET;
244 }
245
246 /*!
247 * @brief Enables the specified I2S peripheral
248 *
249 * @param spi: The I2S can be SPI2,SPI3
250 *
251 * @retval None
252 */
I2S_Enable(SPI_T * spi)253 void I2S_Enable(SPI_T *spi)
254 {
255 spi->I2SCFG_B.I2SEN = BIT_SET;
256 }
257
258 /*!
259 * @brief Disable the specified I2S peripheral
260 *
261 * @param spi: The I2S can be SPI2,SPI3
262 *
263 * @retval None
264 */
I2S_Disable(SPI_T * spi)265 void I2S_Disable(SPI_T *spi)
266 {
267 spi->I2SCFG_B.I2SEN = BIT_RESET;
268 }
269
270 /*!
271 * @brief Configures the data size for the selected SPI.
272 *
273 * @param spi: The SPIx can be 1,2,3,4,5,6.
274 *
275 * @param length: specifies the SPI data size.
276 * This parameter can be one of the following values:
277 * @arg SPI_DATA_LENGTH_16B : Set data frame format to 16bit
278 * @arg SPI_DATA_LENGTH_8B : Set data frame format to 8bit
279 *
280 * @retval None
281 */
SPI_ConfigDataSize(SPI_T * spi,SPI_DATA_LENGTH_T length)282 void SPI_ConfigDataSize(SPI_T *spi, SPI_DATA_LENGTH_T length)
283 {
284 spi->CTRL1_B.DFLSEL = length;
285 }
286
287 /*!
288 * @brief Configures the specified SPI data transfer direction
289 *
290 * @param spi: The SPIx can be 1,2,3,4,5,6.
291 *
292 * @param direction: Select the SPI data transfer direction
293 * The parameter can be one of following values:
294 * @arg SPI_DIRECTION_RX : Selects Rx receive direction
295 * @arg SPI_DIRECTION_TX : Selects Tx transmission direction
296 * @retval None
297 */
SPI_ConfigBiDirectionalLine(SPI_T * spi,SPI_DIRECTION_SELECT_T direction)298 void SPI_ConfigBiDirectionalLine(SPI_T *spi, SPI_DIRECTION_SELECT_T direction)
299 {
300 spi->CTRL1_B.BMOEN = direction;
301 }
302 /*!
303 * @brief Set the SPI NSS internal by Software
304 *
305 * @param spi: The SPIx can be 1,2,3,4,5,6.
306 *
307 * @retval None
308 */
SPI_SetSoftwareNSS(SPI_T * spi)309 void SPI_SetSoftwareNSS(SPI_T *spi)
310 {
311 spi->CTRL1_B.ISSEL = BIT_SET;
312 }
313
314 /*!
315 * @brief Reset the SPI NSS internal by Software
316 *
317 * @param spi: The SPIx can be 1,2,3,4,5,6.
318 *
319 * @retval None
320 */
SPI_ResetSoftwareNSS(SPI_T * spi)321 void SPI_ResetSoftwareNSS(SPI_T *spi)
322 {
323 spi->CTRL1_B.ISSEL = BIT_RESET;
324 }
325
326 /*!
327 * @brief Enables the specified SPI SS output
328 *
329 * @param spi: The SPIx can be 1,2,3,4,5,6.
330 *
331 * @retval None
332 */
SPI_EnableSSOutput(SPI_T * spi)333 void SPI_EnableSSOutput(SPI_T *spi)
334 {
335 spi->CTRL2_B.SSOEN = BIT_SET;
336 }
337
338 /*!
339 * @brief Disable the specified SPI SS output
340 *
341 * @param spi: The SPIx can be 1,2,3,4,5,6.
342 *
343 * @retval None
344 */
SPI_DisableSSOutput(SPI_T * spi)345 void SPI_DisableSSOutput(SPI_T *spi)
346 {
347 spi->CTRL2_B.SSOEN = BIT_RESET;
348 }
349
350 /*!
351 * @brief Enables the specified SPI TI mode
352 *
353 * @param spi: The SPIx can be 1,2,3,4,5,6.
354 *
355 * @retval None
356 */
SPI_EnableTIMode(SPI_T * spi)357 void SPI_EnableTIMode(SPI_T *spi)
358 {
359 spi->CTRL2_B.FRFCFG = BIT_SET;
360 }
361
362 /*!
363 * @brief Disable the specified SPI TI mode
364 *
365 * @param spi: The SPIx can be 1,2,3,4,5,6.
366 *
367 * @retval None
368 */
SPI_DisableTIMode(SPI_T * spi)369 void SPI_DisableTIMode(SPI_T *spi)
370 {
371 spi->CTRL2_B.FRFCFG = BIT_RESET;
372 }
373
374 /*!
375 * @brief Configures the full-duplex mode for the I2S peripheral using its extension
376 * I2S peripheral according to the specified parameters in the i2sConfig.
377 *
378 * @param i2sExt: Specified the I2S peripheral extension block.
379 * The parameter can be one of following values:
380 * @arg I2S2ext : Extended I2S2
381 * @arg I2S3ext : Extended I2S3
382 *
383 * @param i2sConfig: Pointer to the I2S_Config_T structure.
384 *
385 * @retval None
386 *
387 * @note The structure pointed by i2sConfig parameter should be the same used for
388 * the master I2S peripheral.
389 *
390 * @note The I2S full-duplex extension only can be configured in slave mode.
391 */
I2S_ConfigFullDuplex(SPI_T * i2sExt,I2S_Config_T * i2sConfig)392 void I2S_ConfigFullDuplex(SPI_T *i2sExt, I2S_Config_T *i2sConfig)
393 {
394 /** Reset I2SCFG and I2SPSC register */
395 i2sExt->I2SCFG = 0;
396 i2sExt->I2SPSC = 0x0002;
397
398 /** Config the extended I2S */
399 if ((i2sConfig->mode == I2S_MODE_MASTER_TX) || (i2sConfig->mode == I2S_MODE_SLAVE_TX))
400 {
401 i2sExt->I2SCFG_B.I2SMOD = I2S_MODE_SLAVE_RX;
402 i2sExt->I2SCFG_B.I2SSSEL = i2sConfig->standard & 0x03;
403 i2sExt->I2SCFG_B.PFSSEL = (i2sConfig->standard & 0x10) >> 4;
404 i2sExt->I2SCFG_B.CHLEN = i2sConfig->length & 0x01;
405 i2sExt->I2SCFG_B.DATLEN = i2sConfig->length >> 1;
406 i2sExt->I2SCFG_B.CPOL = i2sConfig->polarity;
407 }
408 else
409 {
410 i2sExt->I2SCFG_B.I2SMOD = I2S_MODE_SLAVE_TX;
411 i2sExt->I2SCFG_B.I2SSSEL = i2sConfig->standard & 0x03;
412 i2sExt->I2SCFG_B.PFSSEL = (i2sConfig->standard & 0x10) >> 4;
413 i2sExt->I2SCFG_B.CHLEN = i2sConfig->length & 0x01;
414 i2sExt->I2SCFG_B.DATLEN = i2sConfig->length >> 1;
415 i2sExt->I2SCFG_B.CPOL = i2sConfig->polarity;
416 }
417
418 i2sExt->I2SCFG_B.MODESEL = BIT_SET;
419 }
420
421 /*!
422 * @brief Transmits a Data through the SPIx/I2Sx peripheral.
423 *
424 * @param spi: The SPIx can be 1,2,3,4,5,6.
425 *
426 * @param data: Data to be transmitted
427 *
428 * @retval None
429 */
SPI_I2S_TxData(SPI_T * spi,uint16_t data)430 void SPI_I2S_TxData(SPI_T *spi, uint16_t data)
431 {
432 spi->DATA = data;
433 }
434
435 /*!
436 * @brief Returns the most recent received data by the SPIx/I2Sx peripheral.
437 *
438 * @param spi: The SPIx can be 1,2,3,4,5,6.
439 *
440 * @retval data :The value of the received data
441 *
442 * @retval None
443 */
SPI_I2S_RxData(SPI_T * spi)444 uint16_t SPI_I2S_RxData(SPI_T *spi)
445 {
446 return spi->DATA;
447 }
448
449 /*!
450 * @brief Enables the specified SPI CRC value calculation of the transferred bytes
451 *
452 * @param spi: The SPIx can be 1,2,3,4,5,6.
453 *
454 * @retval None
455 */
SPI_EnableCRC(SPI_T * spi)456 void SPI_EnableCRC(SPI_T *spi)
457 {
458 spi->CTRL1_B.CRCEN = BIT_SET;
459 }
460
461 /*!
462 * @brief Disable the specified SPI CRC value calculation of the transferred bytes
463 *
464 * @param spi: The SPIx can be 1,2,3,4,5,6.
465 *
466 */
SPI_DisableCRC(SPI_T * spi)467 void SPI_DisableCRC(SPI_T *spi)
468 {
469 spi->CTRL1_B.CRCEN = BIT_RESET;
470 }
471
472 /*!
473 * @brief Transmit CRC value
474 *
475 * @param spi: The SPIx can be 1,2,3,4,5,6.
476 *
477 * @retval None
478 */
SPI_TxCRC(SPI_T * spi)479 void SPI_TxCRC(SPI_T *spi)
480 {
481 spi->CTRL1_B.CRCNXT = BIT_SET;
482 }
483
484 /*!
485 * @brief Reads the specified SPI transmit CRC register value
486 *
487 * @param spi: The SPIx can be 1,2,3,4,5,6.
488 *
489 * @retval The SPI transmit CRC register value
490 */
SPI_ReadTxCRC(SPI_T * spi)491 uint16_t SPI_ReadTxCRC(SPI_T *spi)
492 {
493 return spi->TXCRC_B.TXCRC;
494 }
495
496 /*!
497 * @brief Reads the specified SPI receive CRC register value
498 *
499 * @param spi: The SPIx can be 1,2,3,4,5,6.
500 *
501 * @retval The SPI receive CRC register value
502 */
SPI_ReadRxCRC(SPI_T * spi)503 uint16_t SPI_ReadRxCRC(SPI_T *spi)
504 {
505 return spi->RXCRC_B.RXCRC;
506 }
507
508 /*!
509 * @brief Reads the specified SPI CRC Polynomial register value
510 *
511 * @param spi: The SPIx can be 1,2,3,4,5,6.
512 *
513 * @retval The SPI CRC Polynomial register value
514 */
SPI_ReadCRCPolynomial(SPI_T * spi)515 uint16_t SPI_ReadCRCPolynomial(SPI_T *spi)
516 {
517 return spi->CRCPOLY_B.CRCPOLY;
518 }
519
520 /*!
521 * @brief Enables the SPIx/I2Sx DMA interface.
522 *
523 * @param spi: The SPIx can be 1,2,3,4,5,6, When the I2S can be 2,3
524 *
525 * @param dmaReq: specifies the SPI/I2S DMA transfer request
526 * The parameter can be one of following values:
527 * @arg SPI_I2S_DMA_REQ_TX : Tx buffer DMA transfer request
528 * @arg SPI_I2S_DMA_REQ_RX : Rx buffer DMA transfer request
529 *
530 * @retval None
531 */
SPI_I2S_EnableDMA(SPI_T * spi,SPI_I2S_DMA_REQ_T dmaReq)532 void SPI_I2S_EnableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq)
533 {
534 if (dmaReq == SPI_I2S_DMA_REQ_TX)
535 {
536 spi->CTRL2_B.TXDEN = ENABLE;
537 }
538 else
539 {
540 spi->CTRL2_B.RXDEN = ENABLE;
541 }
542 }
543
544 /*!
545 * @brief Disables the SPIx/I2Sx DMA interface.
546 *
547 * @param spi: The SPIx can be 1,2,3,4,5,6., When the I2S can be 2,3
548 *
549 * @param dmaReq: specifies the SPI/I2S DMA transfer request
550 * The parameter can be one of following values:
551 * @arg SPI_I2S_DMA_REQ_TX : Tx buffer DMA transfer request
552 * @arg SPI_I2S_DMA_REQ_RX : Rx buffer DMA transfer request
553 *
554 * @retval None
555 */
SPI_I2S_DisableDMA(SPI_T * spi,SPI_I2S_DMA_REQ_T dmaReq)556 void SPI_I2S_DisableDMA(SPI_T *spi, SPI_I2S_DMA_REQ_T dmaReq)
557 {
558 if (dmaReq == SPI_I2S_DMA_REQ_TX)
559 {
560 spi->CTRL2_B.TXDEN = DISABLE;
561 }
562 else
563 {
564 spi->CTRL2_B.RXDEN = DISABLE;
565 }
566 }
567
568 /*!
569 * @brief Enables the specified SPI/I2S interrupts.
570 *
571 * @param spi: The SPIx can be 1,2,3,4,5,6., When the I2S can be 2,3
572 *
573 * @param interrupt: specifies the TMR interrupts sources
574 * The parameter can be any combination of following values:
575 * @arg SPI_I2S_INT_TXBE : Tx buffer empty interrupt
576 * @arg SPI_I2S_INT_RXBNE : Rx buffer not empty interrupt
577 * @arg SPI_I2S_INT_ERR : Error interrupt
578 *
579 * @retval None
580 */
SPI_I2S_EnableInterrupt(SPI_T * spi,uint32_t interrupt)581 void SPI_I2S_EnableInterrupt(SPI_T *spi, uint32_t interrupt)
582 {
583 spi->CTRL2 |= (uint32_t)(interrupt >> 8);
584 }
585
586 /*!
587 * @brief Disables the specified SPI/I2S interrupts.
588 *
589 * @param spi: The SPIx can be 1,2,3,4,5,6., When the I2S can be 2,3
590 *
591 * @param interrupt: specifies the TMR interrupts sources
592 * The parameter can be any combination of following values:
593 * @arg SPI_I2S_INT_TXBE : Tx buffer empty interrupt
594 * @arg SPI_I2S_INT_RXBNE : Rx buffer not empty interrupt
595 * @arg SPI_I2S_INT_ERR : Error interrupt
596 *
597 * @retval None
598 */
SPI_I2S_DisableInterrupt(SPI_T * spi,uint32_t interrupt)599 void SPI_I2S_DisableInterrupt(SPI_T *spi, uint32_t interrupt)
600 {
601 spi->CTRL2 &= ~((uint32_t)(interrupt >> 8));
602 }
603
604 /*!
605 * @brief Checks whether the specified SPI/I2S flag is set or not.
606 *
607 * @param spi: The SPIx can be 1,2,3,4,5,6., When the I2S can be 2,3
608 *
609 * @param flag: specifies the SPI/I2S flag to check
610 * The parameter can be one of following values:
611 * @arg SPI_FLAG_RXBNE : Receive buffer not empty flag
612 * @arg SPI_FLAG_TXBE : Transmit buffer empty flag
613 * @arg I2S_FLAG_SCHDIR : Side Channel flag
614 * @arg I2S_FLAG_UDR : Underrun Error flag
615 * @arg SPI_FLAG_CRCE : CRC Error flag
616 * @arg SPI_FLAG_ME : Mode Error flag
617 * @arg SPI_FLAG_OVR : Overrun flag
618 * @arg SPI_FLAG_BSY : Busy flag
619 *
620 * @retval SET or RESET
621 */
SPI_I2S_ReadStatusFlag(SPI_T * spi,SPI_FLAG_T flag)622 uint8_t SPI_I2S_ReadStatusFlag(SPI_T *spi, SPI_FLAG_T flag)
623 {
624 return (spi->STS & flag) ? SET : RESET;
625 }
626
627 /*!
628 * @brief Clears the SPIx CRC Error flag
629 *
630 * @param spi: The SPIx can be 1,2,3,4,5,6.
631 *
632 * @param flag: only clears SPI_FLAG_CRCE(CRC Error flag)
633 *
634 * @retval None
635 *
636 * @note 1)SPI_FLAG_OVR: (OverRun error) flag is cleared by software sequence:
637 * a read operation to SPI_DATA register (SPI_I2S_RxData())
638 * followed by a read operation to SPI_STS register (SPI_I2S_ReadStatusFlag()).
639 * 2)I2S_FLAG_UDR: (UnderRun error) flag is cleared:
640 * a read operation to SPI_STS register (SPI_I2S_ReadStatusFlag()).
641 * 3)SPI_FLAG_ME: (Mode Fault) flag is cleared by software sequence:
642 * a read/write operation to SPI_STS register (SPI_I2S_ReadStatusFlag())
643 * followed by a write operation to SPI_CTRL1 register (SPI_Enable()).
644 */
SPI_I2S_ClearStatusFlag(SPI_T * spi,SPI_FLAG_T flag)645 void SPI_I2S_ClearStatusFlag(SPI_T *spi, SPI_FLAG_T flag)
646 {
647 if (flag == SPI_FLAG_CRCE)
648 {
649 spi->STS_B.CRCEFLG = BIT_RESET;
650 }
651 }
652
653 /*!
654 * @brief Checks whether the specified SPI/I2S interrupt has occurred or not.
655 *
656 * @param spi: The SPIx can be 1,2,3,4,5,6., When the I2S can be 2,3
657 *
658 * @param flag: specifies the SPI/I2S interrupt flag to check.
659 * The parameter can be one of following values:
660 * @arg SPI_I2S_INT_RXBNE : Receive buffer not empty interrupt flag
661 * @arg SPI_I2S_INT_TXBE : Transmit buffer empty interrupt flag
662 * @arg SPI_I2S_INT_OVR : Overrun interrupt flag
663 * @arg SPI_INT_CRCE : CRC Error interrupt flag
664 * @arg SPI_INT_ME : Mode Error interrupt flag
665 * @arg I2S_INT_UDR : Underrun Error interrupt flag
666 *
667 * @retval SET or RESET
668 */
SPI_I2S_ReadIntFlag(SPI_T * spi,SPI_I2S_INT_T flag)669 uint8_t SPI_I2S_ReadIntFlag(SPI_T *spi, SPI_I2S_INT_T flag)
670 {
671 uint32_t intEnable;
672 uint32_t intStatus;
673
674 intEnable = (uint32_t)(spi->CTRL2 & (flag >> 8));
675 intStatus = (uint32_t)(spi->STS & flag);
676
677 if (intEnable && intStatus)
678 {
679 return SET;
680 }
681
682 return RESET;
683 }
684
685 /*!
686 * @brief Clears the SPIx CRC Error interrupt flag
687 *
688 * @param spi: The SPIx can be 1,2,3,4,5,6.
689 *
690 * @param flag: only clears SPI_INT_CRCE(CRC Error interrupt flag)
691 *
692 * @retval None
693 *
694 * @note 1)SPI_I2S_INT_OVR: (OverRun interrupt error) flag is cleared by software sequence:
695 * a read operation to SPI_DATA register (SPI_I2S_RxData())
696 * followed by a read operation to SPI_STS register (SPI_I2S_ReadIntFlag()).
697 * 2)I2S_INT_UDR: (UnderRun interrupt error) flag is cleared:
698 * a read operation to SPI_STS register (SPI_I2S_ReadIntFlag()).
699 * 3)SPI_INT_ME: (Mode interrupt Fault) flag is cleared by software sequence:
700 * a read/write operation to SPI_STS register (SPI_I2S_ReadIntFlag())
701 * followed by a write operation to SPI_CTRL1 register (SPI_Enable()).
702 */
SPI_I2S_ClearIntFlag(SPI_T * spi,SPI_I2S_INT_T flag)703 void SPI_I2S_ClearIntFlag(SPI_T *spi, SPI_I2S_INT_T flag)
704 {
705 if (flag == SPI_INT_CRCE)
706 {
707 spi->STS_B.CRCEFLG = BIT_RESET;
708 }
709
710 }
711
712 /**@} end of group SPI_Functions */
713 /**@} end of group SPI_Driver */
714 /**@} end of group APM32F4xx_StdPeriphDriver */
715