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