1 /*!
2 \file gd32l23x_spi.c
3 \brief SPI driver
4
5 \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7
8 /*
9 Copyright (c) 2021, 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 "gd32l23x_spi.h"
36
37 #define SPI_ERROR_HANDLE(s) do{}while(1)
38
39 /* SPI fifo data size */
40 #define SPI_DATASIZE_SUBTRACT_ONE ((uint8_t)0x01U)
41
42 /* SPI/I2S parameter initialization mask */
43 #define SPI_INIT_MASK ((uint32_t)0x00003040U)
44 #define I2S_INIT_MASK ((uint32_t)0x0000F047U)
45 #define SPI_FIFO_INIT_MASK1 ((uint32_t)0x00003840U) /*!< SPI1 parameter initialization mask1 */
46 #define SPI_FIFO_INIT_MASK2 ((uint32_t)0x0000F0FFU) /*!< SPI1 parameter initialization mask2*/
47 #define SPI_FRAMESIZE_MASK ((uint32_t)0x00000800U) /*!< SPI0 frame size mask */
48 #define SPI_BYTEN_MASK ((uint32_t)0x00001000U) /*!< SPI1 access to FIFO mask */
49 #define SPI_TXLVL_EMPTY_MASK ((uint32_t)0x00001800U) /*!< SPI1 TXFIFO empty mask */
50 #define SPI_RXLVL_EMPTY_MASK ((uint32_t)0x00000600U) /*!< SPI1 RXFIFO empty mask */
51
52 /* default value */
53 #define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /*!< default value of SPI_I2SPSC register */
54
55 /* I2S clock source selection, multiplication and division mask */
56 #define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /*!< I2S1 clock source selection */
57 #define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /*!< I2S clock multiplication mask */
58 #define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /*!< I2S clock division mask */
59
60
61 /*!
62 \brief reset SPI and I2S
63 \param[in] spi_periph: SPIx(x=0,1)
64 \param[out] none
65 \retval none
66 */
spi_i2s_deinit(uint32_t spi_periph)67 void spi_i2s_deinit(uint32_t spi_periph)
68 {
69 switch(spi_periph) {
70 case SPI0:
71 /* reset SPI0 */
72 rcu_periph_reset_enable(RCU_SPI0RST);
73 rcu_periph_reset_disable(RCU_SPI0RST);
74 break;
75 case SPI1:
76 /* reset SPI1 and I2S1 */
77 rcu_periph_reset_enable(RCU_SPI1RST);
78 rcu_periph_reset_disable(RCU_SPI1RST);
79 break;
80 default :
81 break;
82 }
83 }
84
85 /*!
86 \brief initialize the parameters of SPI struct with default values
87 \param[in] none
88 \param[out] spi_parameter_struct: the initialized struct spi_parameter_struct pointer
89 \retval none
90 */
spi_struct_para_init(spi_parameter_struct * spi_struct)91 void spi_struct_para_init(spi_parameter_struct *spi_struct)
92 {
93 /* configure the structure with default value */
94 spi_struct->device_mode = SPI_SLAVE;
95 spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
96 spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
97 spi_struct->nss = SPI_NSS_HARD;
98 spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
99 spi_struct->prescale = SPI_PSC_2;
100 spi_struct->endian = SPI_ENDIAN_MSB;
101 }
102
103 /*!
104 \brief initialize SPI parameter
105 \param[in] spi_periph: SPIx(x=0,1)
106 \param[in] spi_struct: SPI parameter initialization stuct members of the structure
107 and the member values are shown as below:
108 device_mode: SPI_MASTER, SPI_SLAVE
109 trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
110 SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
111 frame_size: SPI_FRAMESIZE_4BIT, SPI_FRAMESIZE_5BIT
112 SPI_FRAMESIZE_6BIT, SPI_FRAMESIZE_7BIT
113 SPI_FRAMESIZE_8BIT, SPI_FRAMESIZE_9BIT
114 SPI_FRAMESIZE_10BIT, SPI_FRAMESIZE_11BIT
115 SPI_FRAMESIZE_12BIT, SPI_FRAMESIZE_13BIT
116 SPI_FRAMESIZE_14BIT, SPI_FRAMESIZE_15BIT
117 SPI_FRAMESIZE_16BIT
118 nss: SPI_NSS_SOFT, SPI_NSS_HARD
119 endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
120 clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
121 SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
122 prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
123 \param[out] none
124 \retval ErrStatus: ERROR or SUCCESS
125 */
spi_init(uint32_t spi_periph,spi_parameter_struct * spi_struct)126 ErrStatus spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct)
127 {
128 uint32_t reg1, reg2, reg3 = 0U;
129
130 reg1 = SPI_CTL0(spi_periph);
131 reg1 &= SPI_INIT_MASK;
132
133 reg2 = SPI_CTL0(spi_periph);
134 reg2 &= SPI_FIFO_INIT_MASK1;
135
136 reg3 = SPI_CTL1(spi_periph);
137 reg3 &= SPI_FIFO_INIT_MASK2;
138
139 if(SPI1 == spi_periph) {
140 /* select SPI as master or slave */
141 reg1 |= spi_struct->device_mode;
142 /* select SPI transfer mode */
143 reg1 |= spi_struct->trans_mode;
144 /* select SPI NSS use hardware or software */
145 reg1 |= spi_struct->nss;
146 /* select SPI LSB or MSB */
147 reg1 |= spi_struct->endian;
148 /* select SPI polarity and phase */
149 reg1 |= spi_struct->clock_polarity_phase;
150 /* select SPI prescale to adjust transmit speed */
151 reg1 |= spi_struct->prescale;
152 /* select SPI frame size */
153 /* check SPI0 frame size is 8bits/16bits or not*/
154 if((SPI_FRAMESIZE_8BIT != spi_struct->frame_size) && (SPI_FRAMESIZE_16BIT != spi_struct->frame_size)) {
155 return ERROR;
156 } else {
157 reg1 |= (spi_struct->frame_size & SPI_FRAMESIZE_MASK);
158 }
159
160 /* write to SPI_CTL0 register */
161 SPI_CTL0(spi_periph) = (uint32_t)reg1;
162
163 } else {
164 /* select SPI as master or slave */
165 reg2 |= spi_struct->device_mode;
166 /* select SPI transfer mode */
167 reg2 |= spi_struct->trans_mode;
168 /* select SPI NSS use hardware or software */
169 reg2 |= spi_struct->nss;
170 /* select SPI LSB or MSB */
171 reg2 |= spi_struct->endian;
172 /* select SPI polarity and phase */
173 reg2 |= spi_struct->clock_polarity_phase;
174 /* select SPI prescale to adjust transmit speed */
175 reg2 |= spi_struct->prescale;
176 /* write to SPI_CTL0 register */
177 SPI_CTL0(spi_periph) = (uint32_t)reg2;
178
179 /* select SPI data size */
180 reg3 |= spi_struct->frame_size;
181 /* write to SPI_CTL0 register */
182 SPI_CTL1(spi_periph) = (uint32_t)reg3;
183 }
184
185 /* select SPI mode */
186 SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
187
188 return SUCCESS;
189 }
190
191 /*!
192 \brief enable SPI
193 \param[in] spi_periph: SPIx(x=0,1)
194 \param[out] none
195 \retval none
196 */
spi_enable(uint32_t spi_periph)197 void spi_enable(uint32_t spi_periph)
198 {
199 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
200 }
201
202 /*!
203 \brief disable SPI
204 \param[in] spi_periph: SPIx(x=0,1)
205 \param[out] none
206 \retval none
207 */
spi_disable(uint32_t spi_periph)208 void spi_disable(uint32_t spi_periph)
209 {
210 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
211 }
212
213 /*!
214 \brief initialize I2S parameter
215 \param[in] spi_periph: SPIx(x=1)
216 \param[in] i2s_mode: I2S operation mode
217 only one parameter can be selected which is shown as below:
218 \arg I2S_MODE_SLAVETX: I2S slave transmit mode
219 \arg I2S_MODE_SLAVERX: I2S slave receive mode
220 \arg I2S_MODE_MASTERTX: I2S master transmit mode
221 \arg I2S_MODE_MASTERRX: I2S master receive mode
222 \param[in] i2s_standard: I2S standard
223 only one parameter can be selected which is shown as below:
224 \arg I2S_STD_PHILLIPS: I2S phillips standard
225 \arg I2S_STD_MSB: I2S MSB standard
226 \arg I2S_STD_LSB: I2S LSB standard
227 \arg I2S_STD_PCMSHORT: I2S PCM short standard
228 \arg I2S_STD_PCMLONG: I2S PCM long standard
229 \param[in] i2s_ckpl: I2S idle state clock polarity
230 only one parameter can be selected which is shown as below:
231 \arg I2S_CKPL_LOW: I2S clock polarity low level
232 \arg I2S_CKPL_HIGH: I2S clock polarity high level
233 \param[out] none
234 \retval none
235 */
i2s_init(uint32_t spi_periph,uint32_t i2s_mode,uint32_t i2s_standard,uint32_t i2s_ckpl)236 void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl)
237 {
238 uint32_t reg = 0U;
239 reg = SPI_I2SCTL(spi_periph);
240 reg &= I2S_INIT_MASK;
241
242 /* enable I2S mode */
243 reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
244 /* select I2S mode */
245 reg |= (uint32_t)i2s_mode;
246 /* select I2S standard */
247 reg |= (uint32_t)i2s_standard;
248 /* select I2S polarity */
249 reg |= (uint32_t)i2s_ckpl;
250
251 /* write to SPI_I2SCTL register */
252 SPI_I2SCTL(spi_periph) = (uint32_t)reg;
253 }
254
255 /*!
256 \brief configure I2S prescaler
257 \param[in] spi_periph: SPIx(x=1)
258 \param[in] i2s_audiosample: I2S audio sample rate
259 only one parameter can be selected which is shown as below:
260 \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
261 \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
262 \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
263 \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
264 \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
265 \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
266 \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
267 \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
268 \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
269 \param[in] i2s_frameformat: I2S data length and channel length
270 only one parameter can be selected which is shown as below:
271 \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
272 \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
273 \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
274 \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
275 \param[in] i2s_mckout: I2S master clock output
276 only one parameter can be selected which is shown as below:
277 \arg I2S_MCKOUT_ENABLE: I2S master clock output enable
278 \arg I2S_MCKOUT_DISABLE: I2S master clock output disable
279 \param[out] none
280 \retval none
281 */
i2s_psc_config(uint32_t spi_periph,uint32_t i2s_audiosample,uint32_t i2s_frameformat,uint32_t i2s_mckout)282 void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout)
283 {
284 uint32_t i2sdiv = 2U, i2sof = 0U;
285 uint32_t clks = 0U;
286 uint32_t i2sclock = 0U;
287
288 /* judge whether the audiosample is 0 */
289 if(0U == i2s_audiosample) {
290 SPI_ERROR_HANDLE("the parameter can not be 0 \r\n");
291 }
292
293 /* deinit SPI_I2SPSC register */
294 SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
295
296 /* get the I2S clock source */
297 if(((uint32_t)spi_periph) == SPI1) {
298 /* I2S1 clock source selection */
299 clks = I2S1_CLOCK_SEL;
300 } else {
301 SPI_ERROR_HANDLE("the peripheral must be SPI1 \r\n");
302 }
303
304 if(0U != (RCU_CFG1 & clks)) {
305 /* get RCU PLL2 clock multiplication factor */
306 clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> 12U);
307
308 if((clks > 5U) && (clks < 15U)) {
309 /* multiplier is between 8 and 14 */
310 clks += 2U;
311 } else {
312 if(15U == clks) {
313 /* multiplier is 20 */
314 clks = 20U;
315 }
316 }
317
318 /* get the PREDV1 value */
319 i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> 4U) + 1U);
320 /* calculate i2sclock based on PLL2 and PREDV1 */
321 i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
322 } else {
323 /* get system clock */
324 i2sclock = rcu_clock_freq_get(CK_SYS);
325 }
326
327 /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
328 if(I2S_MCKOUT_ENABLE == i2s_mckout) {
329 clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample);
330 } else {
331 if(I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat) {
332 clks = (uint32_t)(((i2sclock / 32U) * 10U) / i2s_audiosample);
333 } else {
334 clks = (uint32_t)(((i2sclock / 64U) * 10U) / i2s_audiosample);
335 }
336 }
337
338 /* remove the floating point */
339 clks = (clks + 5U) / 10U;
340 i2sof = (clks & 0x00000001U);
341 i2sdiv = ((clks - i2sof) / 2U);
342 i2sof = (i2sof << 8U);
343
344 /* set the default values */
345 if((i2sdiv < 2U) || (i2sdiv > 255U)) {
346 i2sdiv = 2U;
347 i2sof = 0U;
348 }
349
350 /* configure SPI_I2SPSC */
351 SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout);
352
353 /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
354 SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
355 /* configure data frame format */
356 SPI_I2SCTL(spi_periph) |= (uint32_t)i2s_frameformat;
357 }
358
359 /*!
360 \brief enable I2S
361 \param[in] spi_periph: SPIx(x=1)
362 \param[out] none
363 \retval none
364 */
i2s_enable(uint32_t spi_periph)365 void i2s_enable(uint32_t spi_periph)
366 {
367 SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
368 }
369
370 /*!
371 \brief disable I2S
372 \param[in] spi_periph: SPIx(x=1)
373 \param[out] none
374 \retval none
375 */
i2s_disable(uint32_t spi_periph)376 void i2s_disable(uint32_t spi_periph)
377 {
378 SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
379 }
380
381 /*!
382 \brief enable SPI NSS output
383 \param[in] spi_periph: SPIx(x=0,1)
384 \param[out] none
385 \retval none
386 */
spi_nss_output_enable(uint32_t spi_periph)387 void spi_nss_output_enable(uint32_t spi_periph)
388 {
389 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
390 }
391
392 /*!
393 \brief disable SPI NSS output
394 \param[in] spi_periph: SPIx(x=0,1)
395 \param[out] none
396 \retval none
397 */
spi_nss_output_disable(uint32_t spi_periph)398 void spi_nss_output_disable(uint32_t spi_periph)
399 {
400 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
401 }
402
403 /*!
404 \brief SPI NSS pin high level in software mode
405 \param[in] spi_periph: SPIx(x=0,1)
406 \param[out] none
407 \retval none
408 */
spi_nss_internal_high(uint32_t spi_periph)409 void spi_nss_internal_high(uint32_t spi_periph)
410 {
411 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
412 }
413
414 /*!
415 \brief SPI NSS pin low level in software mode
416 \param[in] spi_periph: SPIx(x=0,1)
417 \param[out] none
418 \retval none
419 */
spi_nss_internal_low(uint32_t spi_periph)420 void spi_nss_internal_low(uint32_t spi_periph)
421 {
422 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
423 }
424
425 /*!
426 \brief enable SPI DMA send or receive
427 \param[in] spi_periph: SPIx(x=0,1)
428 \param[in] spi_dma: SPI DMA mode
429 only one parameter can be selected which is shown as below:
430 \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA
431 \arg SPI_DMA_RECEIVE: SPI receive data use DMA
432 \param[out] none
433 \retval none
434 */
spi_dma_enable(uint32_t spi_periph,uint8_t spi_dma)435 void spi_dma_enable(uint32_t spi_periph, uint8_t spi_dma)
436 {
437 if(SPI_DMA_TRANSMIT == spi_dma) {
438 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
439 } else {
440 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
441 }
442 }
443
444 /*!
445 \brief disable SPI DMA send or receive
446 \param[in] spi_periph: SPIx(x=0,1)
447 \param[in] spi_dma: SPI DMA mode
448 only one parameter can be selected which is shown as below:
449 \arg SPI_DMA_TRANSMIT: SPI transmit data use DMA
450 \arg SPI_DMA_RECEIVE: SPI receive data use DMA
451 \param[out] none
452 \retval none
453 */
spi_dma_disable(uint32_t spi_periph,uint8_t spi_dma)454 void spi_dma_disable(uint32_t spi_periph, uint8_t spi_dma)
455 {
456 if(SPI_DMA_TRANSMIT == spi_dma) {
457 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
458 } else {
459 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
460 }
461 }
462
463 /*!
464 \brief configure SPI data frame format
465 \param[in] spi_periph: SPIx(x=0,1)
466 \param[in] frame_format: SPI frame size
467 only one parameter can be selected which is shown as below:
468 \arg SPI_FRAMESIZE_xBIT(x=4,5..16, for SPI0, x=8,16, for SPI1):SPI frame size is x bits
469 \param[out] none
470 \retval ErrStatus: ERROR or SUCCESS
471 */
spi_i2s_data_frame_format_config(uint32_t spi_periph,uint16_t frame_format)472 ErrStatus spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
473 {
474 uint32_t reg;
475 if(SPI1 == spi_periph){
476 /* check SPI1 frame size is 8bits/16bits or not*/
477 if((SPI_FRAMESIZE_8BIT != frame_format) && (SPI_FRAMESIZE_16BIT != frame_format)){
478 return ERROR;
479 }else{
480 /* clear SPI_CTL0_FF16 bit */
481 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
482 /* configure SPI_CTL0_FF16 bit */
483 SPI_CTL0(spi_periph) |= ((uint32_t)frame_format & SPI_FRAMESIZE_MASK);
484 }
485 }else{
486 reg = SPI_CTL1(spi_periph);
487 /* clear SPI_CTL1_DZ bits */
488 reg &= (uint32_t)(~SPI_CTL1_DZ);
489 reg |= (uint32_t)frame_format;
490 /* configure SPI_CTL1_DZ bits */
491 SPI_CTL1(spi_periph) = reg;
492 }
493 return SUCCESS;
494 }
495
496 /*!
497 \brief SPI transmit data
498 \param[in] spi_periph: SPIx(x=0,1)
499 \param[in] data: 16-bit data
500 \param[out] none
501 \retval none
502 */
spi_i2s_data_transmit(uint32_t spi_periph,uint16_t data)503 void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
504 {
505 SPI_DATA(spi_periph) = (uint32_t)data;
506 }
507
508 /*!
509 \brief SPI receive data
510 \param[in] spi_periph: SPIx(x=0,1)
511 \param[out] none
512 \retval 16-bit data
513 */
spi_i2s_data_receive(uint32_t spi_periph)514 uint16_t spi_i2s_data_receive(uint32_t spi_periph)
515 {
516 return ((uint16_t)SPI_DATA(spi_periph));
517 }
518
519 /*!
520 \brief configure SPI bidirectional transfer direction
521 \param[in] spi_periph: SPIx(x=0,1)
522 \param[in] transfer_direction: SPI transfer direction
523 only one parameter can be selected which is shown as below:
524 \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
525 \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
526 \retval none
527 */
spi_bidirectional_transfer_config(uint32_t spi_periph,uint32_t transfer_direction)528 void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
529 {
530 if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction) {
531 /* set the transmit only mode */
532 SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
533 } else {
534 /* set the receive only mode */
535 SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
536 }
537 }
538
539 /*!
540 \brief set SPI CRC polynomial
541 \param[in] spi_periph: SPIx(x=0,1)
542 \param[in] crc_poly: CRC polynomial value
543 \param[out] none
544 \retval none
545 */
spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly)546 void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly)
547 {
548 /* set SPI CRC polynomial */
549 SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
550 }
551
552 /*!
553 \brief get SPI CRC polynomial
554 \param[in] spi_periph: SPIx(x=0,1)
555 \param[out] none
556 \retval 16-bit CRC polynomial
557 */
spi_crc_polynomial_get(uint32_t spi_periph)558 uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
559 {
560 return ((uint16_t)SPI_CRCPOLY(spi_periph));
561 }
562
563 /*!
564 \brief turn on CRC function
565 \param[in] spi_periph: SPIx(x=0,1)
566 \param[out] none
567 \retval none
568 */
spi_crc_on(uint32_t spi_periph)569 void spi_crc_on(uint32_t spi_periph)
570 {
571 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
572 }
573
574 /*!
575 \brief turn off CRC function
576 \param[in] spi_periph: SPIx(x=0,1)
577 \param[out] none
578 \retval none
579 */
spi_crc_off(uint32_t spi_periph)580 void spi_crc_off(uint32_t spi_periph)
581 {
582 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
583 }
584
585 /*!
586 \brief SPI next data is CRC value
587 \param[in] spi_periph: SPIx(x=0,1)
588 \param[out] none
589 \retval none
590 */
spi_crc_next(uint32_t spi_periph)591 void spi_crc_next(uint32_t spi_periph)
592 {
593 SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
594 }
595
596 /*!
597 \brief get SPI CRC send value or receive value
598 \param[in] spi_periph: SPIx(x=0,1)
599 \param[in] crc: SPI crc value
600 only one parameter can be selected which is shown as below:
601 \arg SPI_CRC_TX: get transmit crc value
602 \arg SPI_CRC_RX: get receive crc value
603 \param[out] none
604 \retval 16-bit CRC value
605 */
spi_crc_get(uint32_t spi_periph,uint8_t crc)606 uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc)
607 {
608 if(SPI_CRC_TX == crc) {
609 return ((uint16_t)(SPI_TCRC(spi_periph)));
610 } else {
611 return ((uint16_t)(SPI_RCRC(spi_periph)));
612 }
613 }
614
615 /*!
616 \brief enable SPI TI mode
617 \param[in] spi_periph: SPIx(x=0,1)
618 \param[out] none
619 \retval none
620 */
spi_ti_mode_enable(uint32_t spi_periph)621 void spi_ti_mode_enable(uint32_t spi_periph)
622 {
623 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
624 }
625
626 /*!
627 \brief disable SPI TI mode
628 \param[in] spi_periph: SPIx(x=0,1)
629 \param[out] none
630 \retval none
631 */
spi_ti_mode_disable(uint32_t spi_periph)632 void spi_ti_mode_disable(uint32_t spi_periph)
633 {
634 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
635 }
636
637 /*!
638 \brief enable SPI NSS pulse mode
639 \param[in] spi_periph: SPIx(x=0,1)
640 \param[out] none
641 \retval none
642 */
spi_nssp_mode_enable(uint32_t spi_periph)643 void spi_nssp_mode_enable(uint32_t spi_periph)
644 {
645 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
646 }
647
648 /*!
649 \brief disable SPI NSS pulse mode
650 \param[in] spi_periph: SPIx(x=0,1)
651 \param[out] none
652 \retval none
653 */
spi_nssp_mode_disable(uint32_t spi_periph)654 void spi_nssp_mode_disable(uint32_t spi_periph)
655 {
656 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
657 }
658
659
660 /*!
661 \brief enable quad wire SPI
662 \param[in] spi_periph: SPIx(only x=0)
663 \param[out] none
664 \retval none
665 */
qspi_enable(uint32_t spi_periph)666 void qspi_enable(uint32_t spi_periph)
667 {
668 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
669 }
670
671 /*!
672 \brief disable quad wire SPI
673 \param[in] spi_periph: SPIx(only x=0)
674 \param[out] none
675 \retval none
676 */
qspi_disable(uint32_t spi_periph)677 void qspi_disable(uint32_t spi_periph)
678 {
679 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
680 }
681
682 /*!
683 \brief enable quad wire SPI write
684 \param[in] spi_periph: SPIx(only x=0)
685 \param[out] none
686 \retval none
687 */
qspi_write_enable(uint32_t spi_periph)688 void qspi_write_enable(uint32_t spi_periph)
689 {
690 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
691 }
692
693 /*!
694 \brief enable quad wire SPI read
695 \param[in] spi_periph: SPIx(only x=0)
696 \param[out] none
697 \retval none
698 */
qspi_read_enable(uint32_t spi_periph)699 void qspi_read_enable(uint32_t spi_periph)
700 {
701 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD;
702 }
703
704 /*!
705 \brief enable SPI_IO2 and SPI_IO3 pin output
706 \param[in] spi_periph: SPIx(only x=0)
707 \param[out] none
708 \retval none
709 */
qspi_io23_output_enable(uint32_t spi_periph)710 void qspi_io23_output_enable(uint32_t spi_periph)
711 {
712 SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV;
713 }
714
715 /*!
716 \brief disable SPI_IO2 and SPI_IO3 pin output
717 \param[in] spi_periph: SPIx(only x=0)
718 \param[out] none
719 \retval none
720 */
qspi_io23_output_disable(uint32_t spi_periph)721 void qspi_io23_output_disable(uint32_t spi_periph)
722 {
723 SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV);
724 }
725
726 /*!
727 \brief configure SPI0 access size to FIFO(8bit or 16bit)
728 \param[in] spi_periph: SPIx(x=0)
729 \param[in] fifo_access_size: byte access enable
730 only one parameter can be selected which is shown as below:
731 \arg SPI_HALFWORD_ACCESS: half-word access to FIFO
732 \arg SPI_BYTE_ACCESS: byte access to FIFO
733 \param[out] none
734 \retval none
735 */
spi_fifo_access_size_config(uint32_t spi_periph,uint16_t fifo_access_size)736 void spi_fifo_access_size_config(uint32_t spi_periph, uint16_t fifo_access_size)
737 {
738 /* clear SPI_CTL1_BYTEN bit */
739 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_BYTEN);
740 /* confige SPI_CTL1_BYTEN bit */
741 SPI_CTL1(spi_periph) |= (uint32_t)fifo_access_size;
742 }
743
744 /*!
745 \brief configure SPI0 total number of data to transmit by DMA is odd or not
746 \param[in] spi_periph: SPIx(x=0)
747 \param[in] odd: odd bytes in TX DMA channel
748 only one parameter can be selected which is shown as below:
749 \arg SPI_TXDMA_EVEN: number of byte in TX DMA channel is even
750 \arg SPI_TXDMA_ODD: number of byte in TX DMA channel is odd
751 \param[out] none
752 \retval none
753 */
spi_transmit_odd_config(uint32_t spi_periph,uint16_t odd)754 void spi_transmit_odd_config(uint32_t spi_periph, uint16_t odd)
755 {
756 /* clear SPI_CTL1_TXDMA_ODD bit */
757 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TXDMA_ODD);
758 /* confige SPI_CTL1_TXDMA_ODD bit */
759 SPI_CTL1(spi_periph) |= (uint32_t)odd;
760 }
761
762 /*!
763 \brief configure SPI0 total number of data to receive by DMA is odd or not
764 \param[in] spi_periph: SPIx(x=0)
765 \param[in] odd: odd bytes in RX DMA channel
766 only one parameter can be selected which is shown as below:
767 \arg SPI_RXDMA_EVEN: number of bytes in RX DMA channel is even
768 \arg SPI_RXDMA_ODD: number of bytes in RX DMA channel is odd
769 \param[out] none
770 \retval none
771 */
spi_receive_odd_config(uint32_t spi_periph,uint16_t odd)772 void spi_receive_odd_config(uint32_t spi_periph, uint16_t odd)
773 {
774 /* clear SPI_CTL1_RXDMA_ODD bit */
775 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RXDMA_ODD);
776 /* confige SPI_CTL1_RXDMA_ODD bit */
777 SPI_CTL1(spi_periph) |= (uint32_t)odd;
778 }
779
780 /*!
781 \brief set CRC length
782 \param[in] spi_periph: SPIx(x=0)
783 \param[in] crc_length: CRC length
784 only one parameter can be selected which is shown as below:
785 \arg SPI_CRC_8BIT: CRC length is 8 bits
786 \arg SPI_CRC_16BIT: CRC length is 16 bits
787 \param[out] none
788 \retval none
789 */
spi_crc_length_set(uint32_t spi_periph,uint16_t crc_length)790 void spi_crc_length_set(uint32_t spi_periph, uint16_t crc_length)
791 {
792 /* clear SPI_CTL0_CRCL bit */
793 SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCL);
794 /* confige SPI_CTL0_CRCL bit */
795 SPI_CTL0(spi_periph) |= (uint32_t)crc_length;
796 }
797
798 /*!
799 \brief enable SPI and I2S interrupt
800 \param[in] spi_periph: SPIx(x=0,1)
801 \param[in] interrupt: SPI/I2S interrupt
802 only one parameter can be selected which is shown as below:
803 \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
804 \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
805 \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
806 transmission underrun error and format error interrupt
807 \param[out] none
808 \retval none
809 */
spi_i2s_interrupt_enable(uint32_t spi_periph,uint8_t interrupt)810 void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
811 {
812 switch(interrupt) {
813 /* SPI/I2S transmit buffer empty interrupt */
814 case SPI_I2S_INT_TBE:
815 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
816 break;
817 /* SPI/I2S receive buffer not empty interrupt */
818 case SPI_I2S_INT_RBNE:
819 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
820 break;
821 /* SPI/I2S error */
822 case SPI_I2S_INT_ERR:
823 SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
824 break;
825 default:
826 break;
827 }
828 }
829
830 /*!
831 \brief disable SPI and I2S interrupt
832 \param[in] spi_periph: SPIx(x=0,1)
833 \param[in] interrupt: SPI/I2S interrupt
834 only one parameter can be selected which is shown as below:
835 \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
836 \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
837 \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
838 transmission underrun error and format error interrupt
839 \param[out] none
840 \retval none
841 */
spi_i2s_interrupt_disable(uint32_t spi_periph,uint8_t interrupt)842 void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
843 {
844 switch(interrupt) {
845 /* SPI/I2S transmit buffer empty interrupt */
846 case SPI_I2S_INT_TBE:
847 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
848 break;
849 /* SPI/I2S receive buffer not empty interrupt */
850 case SPI_I2S_INT_RBNE:
851 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
852 break;
853 /* SPI/I2S error */
854 case SPI_I2S_INT_ERR:
855 SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
856 break;
857 default :
858 break;
859 }
860 }
861
862 /*!
863 \brief get SPI and I2S interrupt flag status
864 \param[in] spi_periph: SPIx(x=0,1)
865 \param[in] interrupt: SPI/I2S interrupt flag status
866 only one parameter can be selected which is shown as below:
867 \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
868 \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
869 \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
870 \arg SPI_INT_FLAG_CONFERR: config error interrupt flag
871 \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag
872 \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag
873 \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag
874 \param[out] none
875 \retval FlagStatus: SET or RESET
876 */
spi_i2s_interrupt_flag_get(uint32_t spi_periph,uint8_t interrupt)877 FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
878 {
879 uint32_t reg1 = SPI_STAT(spi_periph);
880 uint32_t reg2 = SPI_CTL1(spi_periph);
881
882 switch(interrupt) {
883 /* SPI/I2S transmit buffer empty interrupt */
884 case SPI_I2S_INT_FLAG_TBE:
885 reg1 = reg1 & SPI_STAT_TBE;
886 reg2 = reg2 & SPI_CTL1_TBEIE;
887 break;
888 /* SPI/I2S receive buffer not empty interrupt */
889 case SPI_I2S_INT_FLAG_RBNE:
890 reg1 = reg1 & SPI_STAT_RBNE;
891 reg2 = reg2 & SPI_CTL1_RBNEIE;
892 break;
893 /* SPI/I2S overrun interrupt */
894 case SPI_I2S_INT_FLAG_RXORERR:
895 reg1 = reg1 & SPI_STAT_RXORERR;
896 reg2 = reg2 & SPI_CTL1_ERRIE;
897 break;
898 /* SPI config error interrupt */
899 case SPI_INT_FLAG_CONFERR:
900 reg1 = reg1 & SPI_STAT_CONFERR;
901 reg2 = reg2 & SPI_CTL1_ERRIE;
902 break;
903 /* SPI CRC error interrupt */
904 case SPI_INT_FLAG_CRCERR:
905 reg1 = reg1 & SPI_STAT_CRCERR;
906 reg2 = reg2 & SPI_CTL1_ERRIE;
907 break;
908 /* SPI/I2S format error interrupt */
909 case SPI_I2S_INT_FLAG_FERR:
910 reg1 = reg1 & SPI_STAT_FERR;
911 reg2 = reg2 & SPI_CTL1_ERRIE;
912 break;
913 default :
914 break;
915 }
916 /*get SPI/I2S interrupt flag status */
917 if(reg1 && reg2) {
918 return SET;
919 } else {
920 return RESET;
921 }
922 }
923
924 /*!
925 \brief get SPI and I2S flag status
926 \param[in] spi_periph: SPIx(x=0,1)
927 \param[in] flag: SPI/I2S flag status
928 only one parameter can be selected which are shown as below:
929 \arg SPI_FLAG_TBE: transmit buffer empty flag
930 \arg SPI_FLAG_RBNE: receive buffer not empty flag
931 \arg SPI_FLAG_TRANS: transmit on-going flag
932 \arg SPI_FLAG_RXORERR: receive overrun error flag
933 \arg SPI_FLAG_CONFERR: mode config error flag
934 \arg SPI_FLAG_CRCERR: CRC error flag
935 \arg SPI_FLAG_FERR: SPI format error interrupt flag
936 \arg I2S_FLAG_TBE: transmit buffer empty flag
937 \arg I2S_FLAG_RBNE: receive buffer not empty flag
938 \arg I2S_FLAG_TRANS: transmit on-going flag
939 \arg I2S_FLAG_RXORERR: overrun error flag
940 \arg I2S_FLAG_TXURERR: underrun error flag
941 \arg I2S_FLAG_CH: channel side flag
942 \arg I2S_FLAG_FERR: I2S format error interrupt flag
943 only for SPI0:
944 \arg SPI_FLAG_TXLVL_EMPTY: SPI TXFIFO is empty
945 \arg SPI_FLAG_TXLVL_QUARTER_FULL: SPI TXFIFO is a quarter of full
946 \arg SPI_FLAG_TXLVL_HAlF_FULL: SPI TXFIFO is a half of full
947 \arg SPI_FLAG_TXLVL_FULL: SPI TXFIFO is full
948 \arg SPI_FLAG_RXLVL_EMPTY: SPI RXFIFO is empty
949 \arg SPI_FLAG_RXLVL_QUARTER_FULL: SPI RXFIFO is a quarter of full
950 \arg SPI_FLAG_RXLVL_HAlF_FULL: SPI RXFIFO is a half of full
951 \arg SPI_FLAG_RXLVL_FULL: SPI RXFIFO is full
952 \param[out] none
953 \retval FlagStatus: SET or RESET
954 */
spi_i2s_flag_get(uint32_t spi_periph,uint32_t flag)955 FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
956 {
957 if(RESET != (SPI_STAT(spi_periph) & flag)) {
958 return SET;
959 } else {
960 if(SPI1 == spi_periph) {
961 /* check TXFIFO is empty or not */
962 if(SPI_TXLVL_EMPTY == flag) {
963 if(RESET != (SPI_STAT(spi_periph) & SPI_TXLVL_EMPTY_MASK)) {
964 return RESET;
965 } else {
966 return SET;
967 }
968 }
969 /* check RXFIFO is empty or not */
970 if(SPI_RXLVL_EMPTY == flag) {
971 if(RESET != (SPI_STAT(spi_periph) & SPI_RXLVL_EMPTY_MASK)) {
972 return RESET;
973 } else {
974 return SET;
975 }
976 }
977 }
978 return RESET;
979 }
980 }
981
982 /*!
983 \brief clear SPI CRC error flag status
984 \param[in] spi_periph: SPIx(x=0,1)
985 \param[out] none
986 \retval none
987 */
spi_crc_error_clear(uint32_t spi_periph)988 void spi_crc_error_clear(uint32_t spi_periph)
989 {
990 SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR);
991 }
992