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