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