1 /*!
2 \file gd32e10x_spi.c
3 \brief SPI driver
4
5 \version 2017-12-26, V1.0.1, firmware for GD32E10x
6 \version 2020-09-30, V1.1.0, firmware for GD32E10x
7 \version 2020-12-31, V1.2.0, firmware for GD32E10x
8 \version 2021-05-31, V1.2.1, firmware for GD32E10x
9 \version 2022-06-16, V1.2.2, firmware for GD32E10x
10 \version 2022-06-30, V1.3.0, firmware for GD32E10x
11 */
12
13 /*
14 Copyright (c) 2022, GigaDevice Semiconductor Inc.
15
16 Redistribution and use in source and binary forms, with or without modification,
17 are permitted provided that the following conditions are met:
18
19 1. Redistributions of source code must retain the above copyright notice, this
20 list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright notice,
22 this list of conditions and the following disclaimer in the documentation
23 and/or other materials provided with the distribution.
24 3. Neither the name of the copyright holder nor the names of its contributors
25 may be used to endorse or promote products derived from this software without
26 specific prior written permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
32 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37 OF SUCH DAMAGE.
38 */
39
40 #include "gd32e10x_spi.h"
41
42 #define SPI_ERROR_HANDLE(s) do{}while(1)
43
44 /* SPI/I2S parameter initialization mask */
45 #define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */
46 #define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */
47
48 /* I2S clock source selection, multiplication and division mask */
49 #define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */
50 #define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */
51 #define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */
52 #define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */
53
54 /* default value and offset */
55 #define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */
56 #define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */
57 #define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */
58
59 /*!
60 \brief reset SPI and I2S
61 \param[in] spi_periph: SPIx(x=0,1,2)
62 \param[out] none
63 \retval none
64 */
spi_i2s_deinit(uint32_t spi_periph)65 void spi_i2s_deinit(uint32_t spi_periph)
66 {
67 switch(spi_periph){
68 case SPI0:
69 /* reset SPI0 */
70 rcu_periph_reset_enable(RCU_SPI0RST);
71 rcu_periph_reset_disable(RCU_SPI0RST);
72 break;
73 case SPI1:
74 /* reset SPI1 and I2S1 */
75 rcu_periph_reset_enable(RCU_SPI1RST);
76 rcu_periph_reset_disable(RCU_SPI1RST);
77 break;
78 case SPI2:
79 /* reset SPI2 and I2S2 */
80 rcu_periph_reset_enable(RCU_SPI2RST);
81 rcu_periph_reset_disable(RCU_SPI2RST);
82 break;
83 default:
84 break;
85 }
86 }
87
88 /*!
89 \brief initialize the parameters of SPI struct with the default values
90 \param[in] spi_struct: SPI parameter struct
91 \param[out] none
92 \retval none
93 */
spi_struct_para_init(spi_parameter_struct * spi_struct)94 void spi_struct_para_init(spi_parameter_struct* spi_struct)
95 {
96 /* set the SPI struct with the default values */
97 spi_struct->device_mode = SPI_SLAVE;
98 spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
99 spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
100 spi_struct->nss = SPI_NSS_HARD;
101 spi_struct->endian = SPI_ENDIAN_MSB;
102 spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
103 spi_struct->prescale = SPI_PSC_2;
104 }
105
106 /*!
107 \brief initialize SPI parameter
108 \param[in] spi_periph: SPIx(x=0,1,2)
109 \param[in] spi_struct: SPI parameter initialization struct members of the structure
110 and the member values are shown as below:
111 device_mode: SPI_MASTER, SPI_SLAVE
112 trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
113 SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
114 frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
115 nss: SPI_NSS_SOFT, SPI_NSS_HARD
116 endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
117 clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
118 SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
119 prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
120 \param[out] none
121 \retval none
122 */
spi_init(uint32_t spi_periph,spi_parameter_struct * spi_struct)123 void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
124 {
125 uint32_t reg = 0U;
126 reg = SPI_CTL0(spi_periph);
127 reg &= SPI_INIT_MASK;
128
129 /* select SPI as master or slave */
130 reg |= spi_struct->device_mode;
131 /* select SPI transfer mode */
132 reg |= spi_struct->trans_mode;
133 /* select SPI frame size */
134 reg |= spi_struct->frame_size;
135 /* select SPI NSS use hardware or software */
136 reg |= spi_struct->nss;
137 /* select SPI LSB or MSB */
138 reg |= spi_struct->endian;
139 /* select SPI polarity and phase */
140 reg |= spi_struct->clock_polarity_phase;
141 /* select SPI prescale to adjust transmit speed */
142 reg |= spi_struct->prescale;
143
144 /* write to SPI_CTL0 register */
145 SPI_CTL0(spi_periph) = (uint32_t)reg;
146
147 SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
148 }
149
150 /*!
151 \brief enable SPI
152 \param[in] spi_periph: SPIx(x=0,1,2)
153 \param[out] none
154 \retval none
155 */
spi_enable(uint32_t spi_periph)156 void spi_enable(uint32_t spi_periph)
157 {
158 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
159 }
160
161 /*!
162 \brief disable SPI
163 \param[in] spi_periph: SPIx(x=0,1,2)
164 \param[out] none
165 \retval none
166 */
spi_disable(uint32_t spi_periph)167 void spi_disable(uint32_t spi_periph)
168 {
169 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
170 }
171
172 /*!
173 \brief initialize I2S parameter
174 \param[in] spi_periph: SPIx(x=1,2)
175 \param[in] mode: I2S operation mode
176 only one parameter can be selected which is shown as below:
177 \arg I2S_MODE_SLAVETX: I2S slave transmit mode
178 \arg I2S_MODE_SLAVERX: I2S slave receive mode
179 \arg I2S_MODE_MASTERTX: I2S master transmit mode
180 \arg I2S_MODE_MASTERRX: I2S master receive mode
181 \param[in] standard: I2S standard
182 only one parameter can be selected which is shown as below:
183 \arg I2S_STD_PHILLIPS: I2S phillips standard
184 \arg I2S_STD_MSB: I2S MSB standard
185 \arg I2S_STD_LSB: I2S LSB standard
186 \arg I2S_STD_PCMSHORT: I2S PCM short standard
187 \arg I2S_STD_PCMLONG: I2S PCM long standard
188 \param[in] ckpl: I2S idle state clock polarity
189 only one parameter can be selected which is shown as below:
190 \arg I2S_CKPL_LOW: I2S clock polarity low level
191 \arg I2S_CKPL_HIGH: I2S clock polarity high level
192 \param[out] none
193 \retval none
194 */
i2s_init(uint32_t spi_periph,uint32_t mode,uint32_t standard,uint32_t ckpl)195 void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
196 {
197 uint32_t reg = 0U;
198 reg = SPI_I2SCTL(spi_periph);
199 reg &= I2S_INIT_MASK;
200
201 /* enable I2S mode */
202 reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
203 /* select I2S mode */
204 reg |= (uint32_t)mode;
205 /* select I2S standard */
206 reg |= (uint32_t)standard;
207 /* select I2S polarity */
208 reg |= (uint32_t)ckpl;
209
210 /* write to SPI_I2SCTL register */
211 SPI_I2SCTL(spi_periph) = (uint32_t)reg;
212 }
213
214 /*!
215 \brief configure I2S prescaler
216 \param[in] spi_periph: SPIx(x=1,2)
217 \param[in] audiosample: I2S audio sample rate
218 only one parameter can be selected which is shown as below:
219 \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
220 \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
221 \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
222 \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
223 \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
224 \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
225 \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
226 \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
227 \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
228 \param[in] frameformat: I2S data length and channel length
229 only one parameter can be selected which is shown as below:
230 \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
231 \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
232 \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
233 \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
234 \param[in] mckout: I2S master clock output
235 only one parameter can be selected which is shown as below:
236 \arg I2S_MCKOUT_ENABLE: I2S master clock output enable
237 \arg I2S_MCKOUT_DISABLE: I2S master clock output disable
238 \param[out] none
239 \retval none
240 */
i2s_psc_config(uint32_t spi_periph,uint32_t audiosample,uint32_t frameformat,uint32_t mckout)241 void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
242 {
243 uint32_t i2sdiv = 2U, i2sof = 0U;
244 uint32_t clks = 0U;
245 uint32_t i2sclock = 0U;
246
247 /* judge whether the audiosample is 0 */
248 if(0U == audiosample){
249 SPI_ERROR_HANDLE("the parameter can not be 0 \r\n");
250 }
251
252 /* deinit SPI_I2SPSC register */
253 SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
254
255 /* get the I2S clock source */
256 if(SPI1 == ((uint32_t)spi_periph)){
257 /* I2S1 clock source selection */
258 clks = I2S1_CLOCK_SEL;
259 }else{
260 /* I2S2 clock source selection */
261 clks = I2S2_CLOCK_SEL;
262 }
263
264 if(0U != (RCU_CFG1 & clks)){
265 /* get RCU PLL2 clock multiplication factor */
266 clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
267
268 if((clks > 5U) && (clks < 15U)){
269 /* multiplier is between 8 and 16 */
270 clks += 2U;
271 }else{
272 if(15U == clks){
273 /* multiplier is 20 */
274 clks = 20U;
275 }
276 }
277
278 /* get the PREDV1 value */
279 i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U);
280 /* calculate I2S clock based on PLL2 and PREDV1 */
281 if(0U != (RCU_CFG1_PLLPRESEL & RCU_CFG1)){
282 i2sclock = (uint32_t)((IRC48M_VALUE / i2sclock) * clks * 2U);
283 }else{
284 i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
285 }
286 }else{
287 /* get system clock */
288 i2sclock = rcu_clock_freq_get(CK_SYS);
289 }
290
291 /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
292 if(I2S_MCKOUT_ENABLE == mckout){
293 clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
294 }else{
295 if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
296 clks = (uint32_t)(((i2sclock / 32U) *10U) / audiosample);
297 }else{
298 clks = (uint32_t)(((i2sclock / 64U) *10U) / audiosample);
299 }
300 }
301
302 /* remove the floating point */
303 clks = (clks + 5U) / 10U;
304 i2sof = (clks & 0x00000001U);
305 i2sdiv = ((clks - i2sof) / 2U);
306 i2sof = (i2sof << 8U);
307
308 /* set the default values */
309 if((i2sdiv < 2U) || (i2sdiv > 255U)){
310 i2sdiv = 2U;
311 i2sof = 0U;
312 }
313
314 /* configure SPI_I2SPSC */
315 SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
316
317 /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
318 SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
319 /* configure data frame format */
320 SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
321 }
322
323 /*!
324 \brief enable I2S
325 \param[in] spi_periph: SPIx(x=1,2)
326 \param[out] none
327 \retval none
328 */
i2s_enable(uint32_t spi_periph)329 void i2s_enable(uint32_t spi_periph)
330 {
331 SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
332 }
333
334 /*!
335 \brief disable I2S
336 \param[in] spi_periph: SPIx(x=1,2)
337 \param[out] none
338 \retval none
339 */
i2s_disable(uint32_t spi_periph)340 void i2s_disable(uint32_t spi_periph)
341 {
342 SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
343 }
344
345 /*!
346 \brief enable SPI NSS output
347 \param[in] spi_periph: SPIx(x=0,1,2)
348 \param[out] none
349 \retval none
350 */
spi_nss_output_enable(uint32_t spi_periph)351 void spi_nss_output_enable(uint32_t spi_periph)
352 {
353 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
354 }
355
356 /*!
357 \brief disable SPI NSS output
358 \param[in] spi_periph: SPIx(x=0,1,2)
359 \param[out] none
360 \retval none
361 */
spi_nss_output_disable(uint32_t spi_periph)362 void spi_nss_output_disable(uint32_t spi_periph)
363 {
364 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
365 }
366
367 /*!
368 \brief SPI NSS pin high level in software mode
369 \param[in] spi_periph: SPIx(x=0,1,2)
370 \param[out] none
371 \retval none
372 */
spi_nss_internal_high(uint32_t spi_periph)373 void spi_nss_internal_high(uint32_t spi_periph)
374 {
375 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
376 }
377
378 /*!
379 \brief SPI NSS pin low level in software mode
380 \param[in] spi_periph: SPIx(x=0,1,2)
381 \param[out] none
382 \retval none
383 */
spi_nss_internal_low(uint32_t spi_periph)384 void spi_nss_internal_low(uint32_t spi_periph)
385 {
386 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
387 }
388
389 /*!
390 \brief enable SPI DMA send or receive
391 \param[in] spi_periph: SPIx(x=0,1,2)
392 \param[in] dma: SPI DMA mode
393 only one parameter can be selected which is shown as below:
394 \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
395 \arg SPI_DMA_RECEIVE: SPI receive data using DMA
396 \param[out] none
397 \retval none
398 */
spi_dma_enable(uint32_t spi_periph,uint8_t dma)399 void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
400 {
401 if(SPI_DMA_TRANSMIT == dma){
402 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
403 }else{
404 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
405 }
406 }
407
408 /*!
409 \brief disable SPI DMA send or receive
410 \param[in] spi_periph: SPIx(x=0,1,2)
411 \param[in] dma: SPI DMA mode
412 only one parameter can be selected which is shown as below:
413 \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
414 \arg SPI_DMA_RECEIVE: SPI receive data using DMA
415 \param[out] none
416 \retval none
417 */
spi_dma_disable(uint32_t spi_periph,uint8_t dma)418 void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
419 {
420 if(SPI_DMA_TRANSMIT == dma){
421 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
422 }else{
423 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
424 }
425 }
426
427 /*!
428 \brief configure SPI/I2S data frame format
429 \param[in] spi_periph: SPIx(x=0,1,2)
430 \param[in] frame_format: SPI frame size
431 only one parameter can be selected which is shown as below:
432 \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
433 \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
434 \param[out] none
435 \retval none
436 */
spi_i2s_data_frame_format_config(uint32_t spi_periph,uint16_t frame_format)437 void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
438 {
439 /* clear SPI_CTL0_FF16 bit */
440 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
441 /* configure SPI_CTL0_FF16 bit */
442 SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
443 }
444
445 /*!
446 \brief SPI transmit data
447 \param[in] spi_periph: SPIx(x=0,1,2)
448 \param[in] data: 16-bit data
449 \param[out] none
450 \retval none
451 */
spi_i2s_data_transmit(uint32_t spi_periph,uint16_t data)452 void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
453 {
454 SPI_DATA(spi_periph) = (uint32_t)data;
455 }
456
457 /*!
458 \brief SPI receive data
459 \param[in] spi_periph: SPIx(x=0,1,2)
460 \param[out] none
461 \retval 16-bit data
462 */
spi_i2s_data_receive(uint32_t spi_periph)463 uint16_t spi_i2s_data_receive(uint32_t spi_periph)
464 {
465 return ((uint16_t)SPI_DATA(spi_periph));
466 }
467
468 /*!
469 \brief configure SPI bidirectional transfer direction
470 \param[in] spi_periph: SPIx(x=0,1,2)
471 \param[in] transfer_direction: SPI transfer direction
472 only one parameter can be selected which is shown as below:
473 \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
474 \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
475 \param[out] none
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)
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)
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 CRC function
515 \param[in] spi_periph: SPIx(x=0,1,2)
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 CRC function
526 \param[in] spi_periph: SPIx(x=0,1,2)
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)
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)
549 \param[in] 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 crc)556 uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
557 {
558 if(SPI_CRC_TX == 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)
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)
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 enable SPI NSS pulse mode
589 \param[in] spi_periph: SPIx(x=0,1,2)
590 \param[out] none
591 \retval none
592 */
spi_nssp_mode_enable(uint32_t spi_periph)593 void spi_nssp_mode_enable(uint32_t spi_periph)
594 {
595 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
596 }
597
598 /*!
599 \brief disable SPI NSS pulse mode
600 \param[in] spi_periph: SPIx(x=0,1,2)
601 \param[out] none
602 \retval none
603 */
spi_nssp_mode_disable(uint32_t spi_periph)604 void spi_nssp_mode_disable(uint32_t spi_periph)
605 {
606 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
607 }
608
609 /*!
610 \brief enable SPI quad wire mode
611 \param[in] spi_periph: SPIx(only x=0)
612 \param[out] none
613 \retval none
614 */
spi_quad_enable(uint32_t spi_periph)615 void spi_quad_enable(uint32_t spi_periph)
616 {
617 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
618 }
619
620 /*!
621 \brief disable SPI quad wire mode
622 \param[in] spi_periph: SPIx(only x=0)
623 \param[out] none
624 \retval none
625 */
spi_quad_disable(uint32_t spi_periph)626 void spi_quad_disable(uint32_t spi_periph)
627 {
628 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
629 }
630
631 /*!
632 \brief enable SPI quad wire mode write
633 \param[in] spi_periph: SPIx(only x=0)
634 \param[out] none
635 \retval none
636 */
spi_quad_write_enable(uint32_t spi_periph)637 void spi_quad_write_enable(uint32_t spi_periph)
638 {
639 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
640 }
641
642 /*!
643 \brief enable SPI quad wire mode read
644 \param[in] spi_periph: SPIx(only x=0)
645 \param[out] none
646 \retval none
647 */
spi_quad_read_enable(uint32_t spi_periph)648 void spi_quad_read_enable(uint32_t spi_periph)
649 {
650 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD;
651 }
652
653 /*!
654 \brief enable SPI quad wire mode SPI_IO2 and SPI_IO3 pin output
655 \param[in] spi_periph: SPIx(only x=0)
656 \param[out] none
657 \retval none
658 */
spi_quad_io23_output_enable(uint32_t spi_periph)659 void spi_quad_io23_output_enable(uint32_t spi_periph)
660 {
661 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
662 }
663
664 /*!
665 \brief disable SPI quad wire mode SPI_IO2 and SPI_IO3 pin output
666 \param[in] spi_periph: SPIx(only x=0)
667 \param[out] none
668 \retval none
669 */
spi_quad_io23_output_disable(uint32_t spi_periph)670 void spi_quad_io23_output_disable(uint32_t spi_periph)
671 {
672 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
673 }
674
675 /*!
676 \brief enable SPI and I2S interrupt
677 \param[in] spi_periph: SPIx(x=0,1,2)
678 \param[in] interrupt: SPI/I2S interrupt
679 only one parameter can be selected which is shown as below:
680 \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
681 \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
682 \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
683 transmission underrun error and format error interrupt
684 \param[out] none
685 \retval none
686 */
spi_i2s_interrupt_enable(uint32_t spi_periph,uint8_t interrupt)687 void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
688 {
689 switch(interrupt){
690 /* SPI/I2S transmit buffer empty interrupt */
691 case SPI_I2S_INT_TBE:
692 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
693 break;
694 /* SPI/I2S receive buffer not empty interrupt */
695 case SPI_I2S_INT_RBNE:
696 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
697 break;
698 /* SPI/I2S error */
699 case SPI_I2S_INT_ERR:
700 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
701 break;
702 default:
703 break;
704 }
705 }
706
707 /*!
708 \brief disable SPI and I2S interrupt
709 \param[in] spi_periph: SPIx(x=0,1,2)
710 \param[in] interrupt: SPI/I2S interrupt
711 only one parameter can be selected which is shown as below:
712 \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
713 \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
714 \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
715 transmission underrun error and format error interrupt
716 \param[out] none
717 \retval none
718 */
spi_i2s_interrupt_disable(uint32_t spi_periph,uint8_t interrupt)719 void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
720 {
721 switch(interrupt){
722 /* SPI/I2S transmit buffer empty interrupt */
723 case SPI_I2S_INT_TBE:
724 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
725 break;
726 /* SPI/I2S receive buffer not empty interrupt */
727 case SPI_I2S_INT_RBNE:
728 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
729 break;
730 /* SPI/I2S error */
731 case SPI_I2S_INT_ERR:
732 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
733 break;
734 default:
735 break;
736 }
737 }
738
739 /*!
740 \brief get SPI and I2S interrupt flag status
741 \param[in] spi_periph: SPIx(x=0,1,2)
742 \param[in] interrupt: SPI/I2S interrupt flag status
743 only one parameter can be selected which is shown as below:
744 \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
745 \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
746 \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
747 \arg SPI_INT_FLAG_CONFERR: config error interrupt flag
748 \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag
749 \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag
750 \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag
751 \param[out] none
752 \retval FlagStatus: SET or RESET
753 */
spi_i2s_interrupt_flag_get(uint32_t spi_periph,uint8_t interrupt)754 FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
755 {
756 uint32_t reg1 = SPI_STAT(spi_periph);
757 uint32_t reg2 = SPI_CTL1(spi_periph);
758
759 switch(interrupt){
760 /* SPI/I2S transmit buffer empty interrupt */
761 case SPI_I2S_INT_FLAG_TBE:
762 reg1 = reg1 & SPI_STAT_TBE;
763 reg2 = reg2 & SPI_CTL1_TBEIE;
764 break;
765 /* SPI/I2S receive buffer not empty interrupt */
766 case SPI_I2S_INT_FLAG_RBNE:
767 reg1 = reg1 & SPI_STAT_RBNE;
768 reg2 = reg2 & SPI_CTL1_RBNEIE;
769 break;
770 /* SPI/I2S overrun interrupt */
771 case SPI_I2S_INT_FLAG_RXORERR:
772 reg1 = reg1 & SPI_STAT_RXORERR;
773 reg2 = reg2 & SPI_CTL1_ERRIE;
774 break;
775 /* SPI config error interrupt */
776 case SPI_INT_FLAG_CONFERR:
777 reg1 = reg1 & SPI_STAT_CONFERR;
778 reg2 = reg2 & SPI_CTL1_ERRIE;
779 break;
780 /* SPI CRC error interrupt */
781 case SPI_INT_FLAG_CRCERR:
782 reg1 = reg1 & SPI_STAT_CRCERR;
783 reg2 = reg2 & SPI_CTL1_ERRIE;
784 break;
785 /* I2S underrun error interrupt */
786 case I2S_INT_FLAG_TXURERR:
787 reg1 = reg1 & SPI_STAT_TXURERR;
788 reg2 = reg2 & SPI_CTL1_ERRIE;
789 break;
790 /* SPI/I2S format error interrupt */
791 case SPI_I2S_INT_FLAG_FERR:
792 reg1 = reg1 & SPI_STAT_FERR;
793 reg2 = reg2 & SPI_CTL1_ERRIE;
794 break;
795 default:
796 break;
797 }
798 /* get SPI/I2S interrupt flag status */
799 if((0U != reg1) && (0U != reg2)){
800 return SET;
801 }else{
802 return RESET;
803 }
804 }
805
806 /*!
807 \brief get SPI and I2S flag status
808 \param[in] spi_periph: SPIx(x=0,1,2)
809 \param[in] flag: SPI/I2S flag status
810 one or more parameters can be selected which are shown as below:
811 \arg SPI_FLAG_TBE: transmit buffer empty flag
812 \arg SPI_FLAG_RBNE: receive buffer not empty flag
813 \arg SPI_FLAG_TRANS: transmit on-going flag
814 \arg SPI_FLAG_RXORERR: receive overrun error flag
815 \arg SPI_FLAG_CONFERR: mode config error flag
816 \arg SPI_FLAG_CRCERR: CRC error flag
817 \arg SPI_FLAG_FERR: format error interrupt flag
818 \arg I2S_FLAG_TBE: transmit buffer empty flag
819 \arg I2S_FLAG_RBNE: receive buffer not empty flag
820 \arg I2S_FLAG_TRANS: transmit on-going flag
821 \arg I2S_FLAG_RXORERR: overrun error flag
822 \arg I2S_FLAG_TXURERR: underrun error flag
823 \arg I2S_FLAG_CH: channel side flag
824 \arg I2S_FLAG_FERR: format error interrupt flag
825 \param[out] none
826 \retval FlagStatus: SET or RESET
827 */
spi_i2s_flag_get(uint32_t spi_periph,uint32_t flag)828 FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
829 {
830 if(RESET != (SPI_STAT(spi_periph) & flag)){
831 return SET;
832 }else{
833 return RESET;
834 }
835 }
836
837 /*!
838 \brief clear SPI CRC error flag status
839 \param[in] spi_periph: SPIx(x=0,1,2)
840 \param[out] none
841 \retval none
842 */
spi_crc_error_clear(uint32_t spi_periph)843 void spi_crc_error_clear(uint32_t spi_periph)
844 {
845 SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR);
846 }
847