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