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