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