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