1 /*!
2     \file    gd32f3x0_spi.c
3     \brief   SPI driver
4 
5     \version 2017-06-06, V1.0.0, firmware for GD32F3x0
6     \version 2019-06-01, V2.0.0, firmware for GD32F3x0
7     \version 2020-09-30, V2.1.0, firmware for GD32F3x0
8 */
9 
10 /*
11     Copyright (c) 2020, GigaDevice Semiconductor Inc.
12 
13     Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15 
16     1. Redistributions of source code must retain the above copyright notice, this
17        list of conditions and the following disclaimer.
18     2. Redistributions in binary form must reproduce the above copyright notice,
19        this list of conditions and the following disclaimer in the documentation
20        and/or other materials provided with the distribution.
21     3. Neither the name of the copyright holder nor the names of its contributors
22        may be used to endorse or promote products derived from this software without
23        specific prior written permission.
24 
25     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36 
37 #include "gd32f3x0_spi.h"
38 
39 #define SPI_INIT_MASK                   ((uint32_t)0x00003040U)  /*!< SPI parameter initialization mask */
40 #define I2S_INIT_MASK                   ((uint32_t)0x0000F047U)  /*!< I2S parameter initialization mask */
41 
42 #define SPI_I2SPSC_DEFAULT_VALUE        ((uint32_t)0x00000002U)  /*!< default value of SPI_I2SPSC register */
43 
44 /*!
45     \brief      reset SPI and I2S
46     \param[in]  spi_periph: SPIx(x=0,1)
47     \param[out] none
48     \retval     none
49 */
spi_i2s_deinit(uint32_t spi_periph)50 void spi_i2s_deinit(uint32_t spi_periph)
51 {
52     switch(spi_periph){
53     case SPI0:
54         /* reset SPI0 and I2S0 */
55         rcu_periph_reset_enable(RCU_SPI0RST);
56         rcu_periph_reset_disable(RCU_SPI0RST);
57         break;
58     case SPI1:
59         /* reset SPI1 */
60         rcu_periph_reset_enable(RCU_SPI1RST);
61         rcu_periph_reset_disable(RCU_SPI1RST);
62         break;
63     default :
64         break;
65     }
66 }
67 
68 /*!
69     \brief      initialize the parameters of SPI struct with the default values
70     \param[in]  spi_struct: SPI parameter stuct
71     \param[out] none
72     \retval     none
73 */
spi_struct_para_init(spi_parameter_struct * spi_struct)74 void spi_struct_para_init(spi_parameter_struct* spi_struct)
75 {
76     /* set the SPI struct with the default values */
77     spi_struct->device_mode = SPI_SLAVE;
78     spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
79     spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
80     spi_struct->nss = SPI_NSS_HARD;
81     spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
82     spi_struct->prescale = SPI_PSC_2;
83 }
84 
85 /*!
86     \brief      initialize SPI parameter
87     \param[in]  spi_periph: SPIx(x=0,1)
88     \param[in]  spi_struct: SPI parameter initialization stuct members of the structure
89                             and the member values are shown as below:
90                   device_mode: SPI_MASTER, SPI_SLAVE
91                   trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
92                               SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
93                   frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
94                   nss: SPI_NSS_SOFT, SPI_NSS_HARD
95                   endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
96                   clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
97                                         SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
98                   prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
99     \param[out] none
100     \retval     none
101 */
spi_init(uint32_t spi_periph,spi_parameter_struct * spi_struct)102 void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
103 {
104     uint32_t reg = 0U;
105     reg = SPI_CTL0(spi_periph);
106     reg &= SPI_INIT_MASK;
107 
108     /* select SPI as master or slave */
109     reg |= spi_struct->device_mode;
110     /* select SPI transfer mode */
111     reg |= spi_struct->trans_mode;
112     /* select SPI frame size */
113     reg |= spi_struct->frame_size;
114     /* select SPI NSS use hardware or software */
115     reg |= spi_struct->nss;
116     /* select SPI LSB or MSB */
117     reg |= spi_struct->endian;
118     /* select SPI polarity and phase */
119     reg |= spi_struct->clock_polarity_phase;
120     /* select SPI prescale to adjust transmit speed */
121     reg |= spi_struct->prescale;
122 
123     /* write to SPI_CTL0 register */
124     SPI_CTL0(spi_periph) = (uint32_t)reg;
125 
126     /* select SPI mode */
127     SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
128 }
129 
130 /*!
131     \brief      enable SPI
132     \param[in]  spi_periph: SPIx(x=0,1)
133     \param[out] none
134     \retval     none
135 */
spi_enable(uint32_t spi_periph)136 void spi_enable(uint32_t spi_periph)
137 {
138     SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
139 }
140 
141 /*!
142     \brief      disable SPI
143     \param[in]  spi_periph: SPIx(x=0,1)
144     \param[out] none
145     \retval     none
146 */
spi_disable(uint32_t spi_periph)147 void spi_disable(uint32_t spi_periph)
148 {
149     SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
150 }
151 
152 
153 #ifdef GD32F350
154 /*!
155     \brief      initialize I2S parameter
156     \param[in]  spi_periph: SPI0
157     \param[in]  mode: I2S operation mode
158                 only one parameter can be selected which is shown as below:
159       \arg        I2S_MODE_SLAVETX: I2S slave transmit mode
160       \arg        I2S_MODE_SLAVERX: I2S slave receive mode
161       \arg        I2S_MODE_MASTERTX: I2S master transmit mode
162       \arg        I2S_MODE_MASTERRX: I2S master receive mode
163     \param[in]  standard: I2S standard
164                 only one parameter can be selected which is shown as below:
165       \arg        I2S_STD_PHILLIPS: I2S phillips standard
166       \arg        I2S_STD_MSB: I2S MSB standard
167       \arg        I2S_STD_LSB: I2S LSB standard
168       \arg        I2S_STD_PCMSHORT: I2S PCM short standard
169       \arg        I2S_STD_PCMLONG: I2S PCM long standard
170     \param[in]  ckpl: I2S idle state clock polarity
171                 only one parameter can be selected which is shown as below:
172       \arg        I2S_CKPL_LOW: I2S clock polarity low level
173       \arg        I2S_CKPL_HIGH: I2S clock polarity high level
174     \param[out] none
175     \retval     none
176 */
i2s_init(uint32_t spi_periph,uint32_t mode,uint32_t standard,uint32_t ckpl)177 void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
178 {
179     uint32_t reg = 0U;
180     reg = SPI_I2SCTL(spi_periph);
181     reg &= I2S_INIT_MASK;
182 
183     /* enable I2S mode */
184     reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
185     /* select I2S mode */
186     reg |= (uint32_t)mode;
187     /* select I2S standard */
188     reg |= (uint32_t)standard;
189     /* select I2S polarity */
190     reg |= (uint32_t)ckpl;
191 
192     /* write to SPI_I2SCTL register */
193     SPI_I2SCTL(spi_periph) = (uint32_t)reg;
194 }
195 
196 /*!
197     \brief      configure I2S prescaler
198     \param[in]  spi_periph: SPI0
199     \param[in]  audiosample: I2S audio sample rate
200                 only one parameter can be selected which is shown as below:
201       \arg        I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
202       \arg        I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
203       \arg        I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
204       \arg        I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
205       \arg        I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
206       \arg        I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
207       \arg        I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
208       \arg        I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
209       \arg        I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
210     \param[in]  frameformat: I2S data length and channel length
211                 only one parameter can be selected which is shown as below:
212       \arg        I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
213       \arg        I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
214       \arg        I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
215       \arg        I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
216     \param[in]  mckout: I2S master clock output
217                 only one parameter can be selected which is shown as below:
218       \arg        I2S_MCKOUT_ENABLE: I2S master clock output enable
219       \arg        I2S_MCKOUT_DISABLE: I2S master clock output disable
220     \param[out] none
221     \retval     none
222 */
i2s_psc_config(uint32_t spi_periph,uint32_t audiosample,uint32_t frameformat,uint32_t mckout)223 void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
224 {
225     uint32_t i2sdiv = 2U, i2sof = 0U;
226     uint32_t clks = 0U;
227     uint32_t i2sclock = 0U;
228 
229     /* deinit SPI_I2SPSC register */
230     SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
231 
232     /* get system clock */
233     i2sclock = rcu_clock_freq_get(CK_SYS);
234 
235     /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
236     if(I2S_MCKOUT_ENABLE == mckout){
237         clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
238     }else{
239         if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
240             clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample);
241         }else{
242             clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample);
243         }
244     }
245 
246     /* remove the floating point */
247     clks = (clks + 5U) / 10U;
248     i2sof = (clks & 0x00000001U);
249     i2sdiv = ((clks - i2sof) / 2U);
250     i2sof  = (i2sof << 8U);
251 
252     /* set the default values */
253     if((i2sdiv < 2U) || (i2sdiv > 255U)){
254         i2sdiv = 2U;
255         i2sof = 0U;
256     }
257 
258     /* configure SPI_I2SPSC */
259     SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
260 
261     /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
262     SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
263     /* configure data frame format */
264     SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
265 }
266 
267 /*!
268     \brief      enable I2S
269     \param[in]  spi_periph: SPI0
270     \param[out] none
271     \retval     none
272 */
i2s_enable(uint32_t spi_periph)273 void i2s_enable(uint32_t spi_periph)
274 {
275     SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
276 }
277 
278 /*!
279     \brief      disable I2S
280     \param[in]  spi_periph: SPI0
281     \param[out] none
282     \retval     none
283 */
i2s_disable(uint32_t spi_periph)284 void i2s_disable(uint32_t spi_periph)
285 {
286     SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
287 }
288 
289 #endif /* GD32F350 */
290 
291 /*!
292     \brief      enable SPI NSS output
293     \param[in]  spi_periph: SPIx(x=0,1)
294     \param[out] none
295     \retval     none
296 */
spi_nss_output_enable(uint32_t spi_periph)297 void spi_nss_output_enable(uint32_t spi_periph)
298 {
299     SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
300 }
301 
302 /*!
303     \brief      disable SPI NSS output
304     \param[in]  spi_periph: SPIx(x=0,1)
305     \param[out] none
306     \retval     none
307 */
spi_nss_output_disable(uint32_t spi_periph)308 void spi_nss_output_disable(uint32_t spi_periph)
309 {
310     SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
311 }
312 
313 /*!
314     \brief      pull NSS pin high in software mode
315     \param[in]  spi_periph: SPIx(x=0,1)
316     \param[out] none
317     \retval     none
318 */
spi_nss_internal_high(uint32_t spi_periph)319 void spi_nss_internal_high(uint32_t spi_periph)
320 {
321     SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
322 }
323 
324 /*!
325     \brief      pull NSS pin low in software mode
326     \param[in]  spi_periph: SPIx(x=0,1)
327     \param[out] none
328     \retval     none
329 */
spi_nss_internal_low(uint32_t spi_periph)330 void spi_nss_internal_low(uint32_t spi_periph)
331 {
332     SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
333 }
334 
335 /*!
336     \brief      enable SPI DMA send or receive
337     \param[in]  spi_periph: SPIx(x=0,1)
338     \param[in]  dma: SPI DMA mode
339                 only one parameter can be selected which is shown as below:
340       \arg        SPI_DMA_TRANSMIT: SPI transmit data using DMA
341       \arg        SPI_DMA_RECEIVE: SPI receive data using DMA
342     \param[out] none
343     \retval     none
344 */
spi_dma_enable(uint32_t spi_periph,uint8_t dma)345 void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
346 {
347     if(SPI_DMA_TRANSMIT == dma){
348         SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
349     }else{
350         SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
351     }
352 }
353 
354 /*!
355     \brief      disable SPI DMA send or receive
356     \param[in]  spi_periph: SPIx(x=0,1)
357     \param[in]  dma: SPI DMA mode
358                 only one parameter can be selected which is shown as below:
359       \arg        SPI_DMA_TRANSMIT: SPI transmit data using DMA
360       \arg        SPI_DMA_RECEIVE: SPI receive data using DMA
361     \param[out] none
362     \retval     none
363 */
spi_dma_disable(uint32_t spi_periph,uint8_t dma)364 void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
365 {
366     if(SPI_DMA_TRANSMIT == dma){
367         SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
368     }else{
369         SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
370     }
371 }
372 
373 /*!
374     \brief      configure SPI/I2S data frame format
375     \param[in]  spi_periph: SPIx(x=0,1)
376     \param[in]  frame_format: SPI frame size
377                 only one parameter can be selected which is shown as below:
378       \arg        SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
379       \arg        SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
380     \param[out] none
381     \retval     none
382 */
spi_i2s_data_frame_format_config(uint32_t spi_periph,uint16_t frame_format)383 void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
384 {
385     /* clear SPI_CTL0_FF16 bit */
386     SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
387     /* confige SPI_CTL0_FF16 bit */
388     SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
389 }
390 
391 /*!
392     \brief      SPI transmit data
393     \param[in]  spi_periph: SPIx(x=0,1)
394     \param[in]  data: 16-bit data
395     \param[out] none
396     \retval     none
397 */
spi_i2s_data_transmit(uint32_t spi_periph,uint16_t data)398 void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
399 {
400     SPI_DATA(spi_periph) = (uint32_t)data;
401 }
402 
403 /*!
404     \brief      SPI receive data
405     \param[in]  spi_periph: SPIx(x=0,1)
406     \param[out] none
407     \retval     16-bit data
408 */
spi_i2s_data_receive(uint32_t spi_periph)409 uint16_t spi_i2s_data_receive(uint32_t spi_periph)
410 {
411     return ((uint16_t)SPI_DATA(spi_periph));
412 }
413 
414 /*!
415     \brief      configure SPI bidirectional transfer direction
416     \param[in]  spi_periph: SPIx(x=0,1)
417     \param[in]  transfer_direction: SPI transfer direction
418                 only one parameter can be selected which is shown as below:
419       \arg        SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
420       \arg        SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
421     \param[out] none
422     \retval     none
423 */
spi_bidirectional_transfer_config(uint32_t spi_periph,uint32_t transfer_direction)424 void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
425 {
426     if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){
427         /* set the transmit only mode */
428         SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
429     }else{
430         /* set the receive only mode */
431         SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
432     }
433 }
434 
435 /*!
436     \brief      set CRC polynomial
437     \param[in]  spi_periph: SPIx(x=0,1)
438     \param[in]  crc_poly: CRC polynomial value
439     \param[out] none
440     \retval     none
441 */
spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly)442 void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly)
443 {
444     /* enable SPI CRC */
445     SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
446     /* set SPI CRC polynomial */
447     SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
448 }
449 
450 /*!
451     \brief      get SPI CRC polynomial
452     \param[in]  spi_periph: SPIx(x=0,1)
453     \param[out] none
454     \retval     16-bit CRC polynomial
455 */
spi_crc_polynomial_get(uint32_t spi_periph)456 uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
457 {
458     return ((uint16_t)SPI_CRCPOLY(spi_periph));
459 }
460 
461 /*!
462     \brief      turn on CRC function
463     \param[in]  spi_periph: SPIx(x=0,1)
464     \param[out] none
465     \retval     none
466 */
spi_crc_on(uint32_t spi_periph)467 void spi_crc_on(uint32_t spi_periph)
468 {
469     SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
470 }
471 
472 /*!
473     \brief      turn off CRC function
474     \param[in]  spi_periph: SPIx(x=0,1)
475     \param[out] none
476     \retval     none
477 */
spi_crc_off(uint32_t spi_periph)478 void spi_crc_off(uint32_t spi_periph)
479 {
480     SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
481 }
482 
483 /*!
484     \brief      SPI next data is CRC value
485     \param[in]  spi_periph: SPIx(x=0,1)
486     \param[out] none
487     \retval     none
488 */
spi_crc_next(uint32_t spi_periph)489 void spi_crc_next(uint32_t spi_periph)
490 {
491     SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
492 }
493 
494 /*!
495     \brief      get SPI CRC send value or receive value
496     \param[in]  spi_periph: SPIx(x=0,1)
497     \param[in]  crc: SPI crc value
498       \arg        SPI_CRC_TX: get transmit crc value
499       \arg        SPI_CRC_RX: get receive crc value
500     \param[out] none
501     \retval     16-bit CRC value
502 */
spi_crc_get(uint32_t spi_periph,uint8_t crc)503 uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc)
504 {
505     if(SPI_CRC_TX == crc){
506         return ((uint16_t)(SPI_TCRC(spi_periph)));
507     }else{
508         return ((uint16_t)(SPI_RCRC(spi_periph)));
509     }
510 }
511 
512 /*!
513     \brief      enable SPI TI mode
514     \param[in]  spi_periph: SPIx(x=0,1)
515     \param[out] none
516     \retval     none
517 */
spi_ti_mode_enable(uint32_t spi_periph)518 void spi_ti_mode_enable(uint32_t spi_periph)
519 {
520     SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
521 }
522 
523 /*!
524     \brief      disable SPI TI mode
525     \param[in]  spi_periph: SPIx(x=0,1)
526     \param[out] none
527     \retval     none
528 */
spi_ti_mode_disable(uint32_t spi_periph)529 void spi_ti_mode_disable(uint32_t spi_periph)
530 {
531     SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
532 }
533 
534 /*!
535     \brief      enable SPI NSS pulse mode
536     \param[in]  spi_periph: SPIx(x=0,1)
537     \param[out] none
538     \retval     none
539 */
spi_nssp_mode_enable(uint32_t spi_periph)540 void spi_nssp_mode_enable(uint32_t spi_periph)
541 {
542     SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
543 }
544 
545 /*!
546     \brief      disable SPI NSS pulse mode
547     \param[in]  spi_periph: SPIx(x=0,1)
548     \param[out] none
549     \retval     none
550 */
spi_nssp_mode_disable(uint32_t spi_periph)551 void spi_nssp_mode_disable(uint32_t spi_periph)
552 {
553     SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
554 }
555 
556 /*!
557     \brief      enable quad wire SPI
558     \param[in]  spi_periph: SPI1
559     \param[out] none
560     \retval     none
561 */
qspi_enable(uint32_t spi_periph)562 void qspi_enable(uint32_t spi_periph)
563 {
564     SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
565 }
566 
567 /*!
568     \brief      disable quad wire SPI
569     \param[in]  spi_periph: SPI1
570     \param[out] none
571     \retval     none
572 */
qspi_disable(uint32_t spi_periph)573 void qspi_disable(uint32_t spi_periph)
574 {
575     SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
576 }
577 
578 /*!
579     \brief      enable quad wire SPI write
580     \param[in]  spi_periph: SPI1
581     \param[out] none
582     \retval     none
583 */
qspi_write_enable(uint32_t spi_periph)584 void qspi_write_enable(uint32_t spi_periph)
585 {
586     SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
587 }
588 
589 /*!
590     \brief      enable quad wire SPI read
591     \param[in]  spi_periph: SPI1
592     \param[out] none
593     \retval     none
594 */
qspi_read_enable(uint32_t spi_periph)595 void qspi_read_enable(uint32_t spi_periph)
596 {
597     SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD;
598 }
599 
600 /*!
601     \brief      enable SPI_IO2 and SPI_IO3 pin output
602     \param[in]  spi_periph: SPI1
603     \param[out] none
604     \retval     none
605 */
qspi_io23_output_enable(uint32_t spi_periph)606 void qspi_io23_output_enable(uint32_t spi_periph)
607 {
608     SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
609 }
610 
611  /*!
612     \brief      disable SPI_IO2 and SPI_IO3 pin output
613     \param[in]  spi_periph: SPI1
614     \param[out] none
615     \retval     none
616 */
qspi_io23_output_disable(uint32_t spi_periph)617  void qspi_io23_output_disable(uint32_t spi_periph)
618 {
619     SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
620 }
621 
622 /*!
623     \brief      enable SPI and I2S interrupt
624     \param[in]  spi_periph: SPIx(x=0,1)
625     \param[in]  interrupt: SPI/I2S interrupt
626                 only one parameter can be selected which is shown as below:
627       \arg        SPI_I2S_INT_TBE: transmit buffer empty interrupt
628       \arg        SPI_I2S_INT_RBNE: receive buffer not empty interrupt
629       \arg        SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
630                                    transmission underrun error and format error interrupt
631     \param[out] none
632     \retval     none
633 */
spi_i2s_interrupt_enable(uint32_t spi_periph,uint8_t interrupt)634 void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
635 {
636     switch(interrupt){
637     /* SPI/I2S transmit buffer empty interrupt */
638     case SPI_I2S_INT_TBE:
639         SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
640         break;
641     /* SPI/I2S receive buffer not empty interrupt */
642     case SPI_I2S_INT_RBNE:
643         SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
644         break;
645     /* SPI/I2S error */
646     case SPI_I2S_INT_ERR:
647         SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
648         break;
649     default:
650         break;
651     }
652 }
653 
654 /*!
655     \brief      disable SPI and I2S interrupt
656     \param[in]  spi_periph: SPIx(x=0,1)
657     \param[in]  interrupt: SPI/I2S interrupt
658                 only one parameter can be selected which is shown as below:
659       \arg        SPI_I2S_INT_TBE: transmit buffer empty interrupt
660       \arg        SPI_I2S_INT_RBNE: receive buffer not empty interrupt
661       \arg        SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
662                                    transmission underrun error and format error interrupt
663     \param[out] none
664     \retval     none
665 */
spi_i2s_interrupt_disable(uint32_t spi_periph,uint8_t interrupt)666 void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
667 {
668     switch(interrupt){
669     /* SPI/I2S transmit buffer empty interrupt */
670     case SPI_I2S_INT_TBE:
671         SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
672         break;
673     /* SPI/I2S receive buffer not empty interrupt */
674     case SPI_I2S_INT_RBNE:
675         SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
676         break;
677     /* SPI/I2S error */
678     case SPI_I2S_INT_ERR:
679         SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
680         break;
681     default :
682         break;
683     }
684 }
685 
686 /*!
687     \brief      get SPI and I2S interrupt flag status
688     \param[in]  spi_periph: SPIx(x=0,1)
689     \param[in]  interrupt: SPI/I2S interrupt flag status
690                 only one parameter can be selected which is shown as below:
691       \arg        SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
692       \arg        SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
693       \arg        SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
694       \arg        SPI_INT_FLAG_CONFERR: config error interrupt flag
695       \arg        SPI_INT_FLAG_CRCERR: CRC error interrupt flag
696       \arg        I2S_INT_FLAG_TXURERR: underrun error interrupt flag
697       \arg        SPI_I2S_INT_FLAG_FERR: format error interrupt flag
698     \param[out] none
699     \retval     FlagStatus: SET or RESET
700 */
spi_i2s_interrupt_flag_get(uint32_t spi_periph,uint8_t interrupt)701 FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
702 {
703     uint32_t reg1 = SPI_STAT(spi_periph);
704     uint32_t reg2 = SPI_CTL1(spi_periph);
705 
706     switch(interrupt){
707     /* SPI/I2S transmit buffer empty interrupt */
708     case SPI_I2S_INT_FLAG_TBE:
709         reg1 = reg1 & SPI_STAT_TBE;
710         reg2 = reg2 & SPI_CTL1_TBEIE;
711         break;
712     /* SPI/I2S receive buffer not empty interrupt */
713     case SPI_I2S_INT_FLAG_RBNE:
714         reg1 = reg1 & SPI_STAT_RBNE;
715         reg2 = reg2 & SPI_CTL1_RBNEIE;
716         break;
717     /* SPI/I2S overrun interrupt */
718     case SPI_I2S_INT_FLAG_RXORERR:
719         reg1 = reg1 & SPI_STAT_RXORERR;
720         reg2 = reg2 & SPI_CTL1_ERRIE;
721         break;
722     /* SPI config error interrupt */
723     case SPI_INT_FLAG_CONFERR:
724         reg1 = reg1 & SPI_STAT_CONFERR;
725         reg2 = reg2 & SPI_CTL1_ERRIE;
726         break;
727     /* SPI CRC error interrupt */
728     case SPI_INT_FLAG_CRCERR:
729         reg1 = reg1 & SPI_STAT_CRCERR;
730         reg2 = reg2 & SPI_CTL1_ERRIE;
731         break;
732     /* I2S underrun error interrupt */
733     case I2S_INT_FLAG_TXURERR:
734         reg1 = reg1 & SPI_STAT_TXURERR;
735         reg2 = reg2 & SPI_CTL1_ERRIE;
736         break;
737     /* SPI/I2S format error interrupt */
738     case SPI_I2S_INT_FLAG_FERR:
739         reg1 = reg1 & SPI_STAT_FERR;
740         reg2 = reg2 & SPI_CTL1_ERRIE;
741         break;
742     default :
743         break;
744     }
745     /*get SPI/I2S interrupt flag status */
746     if((0U != reg1) && (0U != reg2)){
747         return SET;
748     }else{
749         return RESET;
750     }
751 }
752 
753 /*!
754     \brief      get SPI and I2S flag status
755     \param[in]  spi_periph: SPIx(x=0,1)
756     \param[in]  flag: SPI/I2S flag status
757                 one or more parameters can be selected which are shown as below:
758       \arg        SPI_FLAG_TBE: transmit buffer empty flag
759       \arg        SPI_FLAG_RBNE: receive buffer not empty flag
760       \arg        SPI_FLAG_TRANS: transmit on-going flag
761       \arg        SPI_FLAG_RXORERR: receive overrun error flag
762       \arg        SPI_FLAG_CONFERR: mode config error flag
763       \arg        SPI_FLAG_CRCERR: CRC error flag
764       \arg        SPI_FLAG_FERR: format error interrupt flag
765       \arg        I2S_FLAG_TBE: transmit buffer empty flag
766       \arg        I2S_FLAG_RBNE: receive buffer not empty flag
767       \arg        I2S_FLAG_TRANS: transmit on-going flag
768       \arg        I2S_FLAG_RXORERR: overrun error flag
769       \arg        I2S_FLAG_TXURERR: underrun error flag
770       \arg        I2S_FLAG_CH: channel side flag
771       \arg        I2S_FLAG_FERR: format error interrupt flag
772     \param[out] none
773     \retval     FlagStatus: SET or RESET
774 */
spi_i2s_flag_get(uint32_t spi_periph,uint32_t flag)775 FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
776 {
777     if(RESET != (SPI_STAT(spi_periph) & flag)){
778         return SET;
779     }else{
780         return RESET;
781     }
782 }
783 
784 /*!
785     \brief      clear SPI CRC error flag status
786     \param[in]  spi_periph: SPIx(x=0,1)
787     \param[out] none
788     \retval     none
789 */
spi_crc_error_clear(uint32_t spi_periph)790 void spi_crc_error_clear(uint32_t spi_periph)
791 {
792     SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR);
793 }
794