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