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