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