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