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