1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-12-20 BruceOu first implementation
9 */
10 #include "drv_spi.h"
11
12 #ifdef RT_USING_SPI
13
14 #if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) || defined(BSP_USING_SPI4)
15 #define LOG_TAG "drv.spi"
16
17 #include <rtdbg.h>
18
19 #ifdef BSP_USING_SPI0
20 static struct rt_spi_bus spi_bus0;
21 #endif
22 #ifdef BSP_USING_SPI1
23 static struct rt_spi_bus spi_bus1;
24 #endif
25 #ifdef BSP_USING_SPI2
26 static struct rt_spi_bus spi_bus2;
27 #endif
28 #ifdef BSP_USING_SPI3
29 static struct rt_spi_bus spi_bus3;
30 #endif
31 #ifdef BSP_USING_SPI4
32 static struct rt_spi_bus spi_bus4;
33 #endif
34
35 static const struct gd32_spi spi_bus_obj[] = {
36
37 #ifdef BSP_USING_SPI0
38 {
39 SPI0,
40 "spi0",
41 RCU_SPI0,
42 RCU_GPIOA,
43 &spi_bus0,
44 GPIOA,
45 #if defined SOC_SERIES_GD32F4xx
46 GPIO_AF_5,
47 #endif
48 #if defined SOC_SERIES_GD32E23x
49 GPIO_AF_0,
50 #endif
51 GPIO_PIN_5,
52 GPIO_PIN_6,
53 GPIO_PIN_7,
54 },
55 #endif /* BSP_USING_SPI0 */
56
57 #ifdef BSP_USING_SPI1
58 {
59 SPI1,
60 "spi1",
61 RCU_SPI1,
62 RCU_GPIOB,
63 &spi_bus1,
64 GPIOB,
65 #if defined SOC_SERIES_GD32F4xx
66 GPIO_AF_5,
67 #endif
68 #if defined SOC_SERIES_GD32E23x
69 GPIO_AF_0,
70 #endif
71
72 #if defined SOC_SERIES_GD32E23x
73 GPIO_PIN_13,
74 #else
75 GPIO_PIN_12,
76 #endif
77 GPIO_PIN_14,
78 GPIO_PIN_15,
79 },
80 #endif /* BSP_USING_SPI1 */
81
82 #ifdef BSP_USING_SPI2
83 {
84 SPI2,
85 "spi2",
86 RCU_SPI2,
87 RCU_GPIOB,
88 &spi_bus2,
89 GPIOB,
90 #if defined SOC_SERIES_GD32F4xx
91 GPIO_AF_6,
92 #endif
93 GPIO_PIN_3,
94 GPIO_PIN_4,
95 GPIO_PIN_5,
96 },
97 #endif /* BSP_USING_SPI2 */
98
99 #ifdef BSP_USING_SPI3
100 {
101 SPI3,
102 "spi3",
103 RCU_SPI3,
104 RCU_GPIOE,
105 &spi_bus3,
106 GPIOB,
107 #if defined SOC_SERIES_GD32F4xx
108 GPIO_AF_5,
109 #endif
110 GPIO_PIN_2,
111 GPIO_PIN_5,
112 GPIO_PIN_6,
113 },
114 #endif /* BSP_USING_SPI3 */
115
116 #ifdef BSP_USING_SPI4
117 {
118 SPI4,
119 "spi4",
120 RCU_SPI4,
121 RCU_GPIOF,
122 &spi_bus4,
123 GPIOF,
124 #if defined SOC_SERIES_GD32F4xx
125 GPIO_AF_5,
126 #endif
127 GPIO_PIN_7,
128 GPIO_PIN_8,
129 GPIO_PIN_9,
130 }
131 #endif /* BSP_USING_SPI4 */
132 };
133
134 /* private rt-thread spi ops function */
135 static rt_err_t spi_configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration);
136 static rt_ssize_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message);
137
138 static struct rt_spi_ops gd32_spi_ops =
139 {
140 .configure = spi_configure,
141 .xfer = spixfer,
142 };
143
144 /**
145 * @brief SPI Initialization
146 * @param gd32_spi: SPI BUS
147 * @retval None
148 */
gd32_spi_init(struct gd32_spi * gd32_spi)149 static void gd32_spi_init(struct gd32_spi *gd32_spi)
150 {
151 /* enable SPI clock */
152 rcu_periph_clock_enable(gd32_spi->spi_clk);
153 rcu_periph_clock_enable(gd32_spi->gpio_clk);
154
155 #if defined SOC_SERIES_GD32F4xx || defined SOC_SERIES_GD32E23x
156 /*GPIO pin configuration*/
157 gpio_af_set(gd32_spi->spi_port, gd32_spi->alt_func_num, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin);
158
159 gpio_mode_set(gd32_spi->spi_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin);
160 #if defined SOC_SERIES_GD32E23x
161 gpio_output_options_set(gd32_spi->spi_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin);
162 #else
163 gpio_output_options_set(gd32_spi->spi_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gd32_spi->sck_pin | gd32_spi->mosi_pin | gd32_spi->miso_pin);
164 #endif
165 #else
166 /* Init SPI SCK MOSI */
167 gpio_init(gd32_spi->spi_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, gd32_spi->sck_pin | gd32_spi->mosi_pin);
168
169 /* Init SPI MISO */
170 gpio_init(gd32_spi->spi_port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, gd32_spi->miso_pin);
171 #endif
172
173 }
174
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)175 static rt_err_t spi_configure(struct rt_spi_device* device,
176 struct rt_spi_configuration* configuration)
177 {
178 struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus;
179 struct gd32_spi *spi_device = (struct gd32_spi *)spi_bus->parent.user_data;
180 spi_parameter_struct spi_init_struct;
181 uint32_t spi_periph = spi_device->spi_periph;
182
183 RT_ASSERT(device != RT_NULL);
184 RT_ASSERT(configuration != RT_NULL);
185
186 /* Init SPI */
187 gd32_spi_init(spi_device);
188
189 /* data_width */
190 if(configuration->data_width <= 8)
191 {
192 spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
193 }
194 else if(configuration->data_width <= 16)
195 {
196 spi_init_struct.frame_size = SPI_FRAMESIZE_16BIT;
197 }
198 else
199 {
200 return -RT_EIO;
201 }
202
203 /* baudrate */
204 {
205 rcu_clock_freq_enum spi_src;
206 uint32_t spi_apb_clock;
207 uint32_t max_hz;
208
209 max_hz = configuration->max_hz;
210
211 LOG_D("sys freq: %d\n", rcu_clock_freq_get(CK_SYS));
212 LOG_D("CK_APB2 freq: %d\n", rcu_clock_freq_get(CK_APB2));
213 LOG_D("max freq: %d\n", max_hz);
214
215 #if defined SOC_SERIES_GD32E23x
216 spi_src = CK_APB2;
217 #else
218 if (spi_periph == SPI1 || spi_periph == SPI2)
219 {
220 spi_src = CK_APB1;
221 }
222 else
223 {
224 spi_src = CK_APB2;
225 }
226 #endif
227 spi_apb_clock = rcu_clock_freq_get(spi_src);
228
229 if(max_hz >= spi_apb_clock/2)
230 {
231 spi_init_struct.prescale = SPI_PSC_2;
232 }
233 else if (max_hz >= spi_apb_clock/4)
234 {
235 spi_init_struct.prescale = SPI_PSC_4;
236 }
237 else if (max_hz >= spi_apb_clock/8)
238 {
239 spi_init_struct.prescale = SPI_PSC_8;
240 }
241 else if (max_hz >= spi_apb_clock/16)
242 {
243 spi_init_struct.prescale = SPI_PSC_16;
244 }
245 else if (max_hz >= spi_apb_clock/32)
246 {
247 spi_init_struct.prescale = SPI_PSC_32;
248 }
249 else if (max_hz >= spi_apb_clock/64)
250 {
251 spi_init_struct.prescale = SPI_PSC_64;
252 }
253 else if (max_hz >= spi_apb_clock/128)
254 {
255 spi_init_struct.prescale = SPI_PSC_128;
256 }
257 else
258 {
259 /* min prescaler 256 */
260 spi_init_struct.prescale = SPI_PSC_256;
261 }
262 } /* baudrate */
263
264 switch(configuration->mode & RT_SPI_MODE_3)
265 {
266 case RT_SPI_MODE_0:
267 spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
268 break;
269 case RT_SPI_MODE_1:
270 spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
271 break;
272 case RT_SPI_MODE_2:
273 spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
274 break;
275 case RT_SPI_MODE_3:
276 spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
277 break;
278 }
279
280 /* MSB or LSB */
281 if(configuration->mode & RT_SPI_MSB)
282 {
283 spi_init_struct.endian = SPI_ENDIAN_MSB;
284 }
285 else
286 {
287 spi_init_struct.endian = SPI_ENDIAN_LSB;
288 }
289
290 spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
291 spi_init_struct.device_mode = SPI_MASTER;
292 spi_init_struct.nss = SPI_NSS_SOFT;
293
294 spi_crc_off(spi_periph);
295
296 /* init SPI */
297 spi_init(spi_periph, &spi_init_struct);
298 /* Enable SPI_MASTER */
299 spi_enable(spi_periph);
300
301 return RT_EOK;
302 };
303
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)304 static rt_ssize_t spixfer(struct rt_spi_device* device, struct rt_spi_message* message)
305 {
306 struct rt_spi_bus * gd32_spi_bus = (struct rt_spi_bus *)device->bus;
307 struct gd32_spi *spi_device = (struct gd32_spi *)gd32_spi_bus->parent.user_data;
308 struct rt_spi_configuration * config = &device->config;
309 rt_base_t cs_pin = (rt_base_t)device->parent.user_data;
310 uint32_t spi_periph = spi_device->spi_periph;
311
312 RT_ASSERT(device != NULL);
313 RT_ASSERT(message != NULL);
314
315 /* take CS */
316 if(message->cs_take)
317 {
318 rt_pin_write(cs_pin, PIN_LOW);
319 LOG_D("spi take cs\n");
320 }
321
322 {
323 if(config->data_width <= 8)
324 {
325 const rt_uint8_t * send_ptr = message->send_buf;
326 rt_uint8_t * recv_ptr = message->recv_buf;
327 rt_uint32_t size = message->length;
328
329 LOG_D("spi poll transfer start: %d\n", size);
330
331 while(size--)
332 {
333 rt_uint8_t data = 0xFF;
334
335 if(send_ptr != RT_NULL)
336 {
337 data = *send_ptr++;
338 }
339
340 /* Todo: replace register read/write by gd32f4 lib */
341 /* Wait until the transmit buffer is empty */
342 while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE));
343 /* Send the byte */
344 spi_i2s_data_transmit(spi_periph, data);
345
346 /* Wait until a data is received */
347 while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE));
348 /* Get the received data */
349 data = spi_i2s_data_receive(spi_periph);
350
351 if(recv_ptr != RT_NULL)
352 {
353 *recv_ptr++ = data;
354 }
355 }
356 LOG_D("spi poll transfer finsh\n");
357 }
358 else if(config->data_width <= 16)
359 {
360 const rt_uint16_t * send_ptr = message->send_buf;
361 rt_uint16_t * recv_ptr = message->recv_buf;
362 rt_uint32_t size = message->length;
363
364 while(size--)
365 {
366 rt_uint16_t data = 0xFF;
367
368 if(send_ptr != RT_NULL)
369 {
370 data = *send_ptr++;
371 }
372
373 /* Wait until the transmit buffer is empty */
374 while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE));
375 /* Send the byte */
376 spi_i2s_data_transmit(spi_periph, data);
377
378 /* Wait until a data is received */
379 while(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE));
380 /* Get the received data */
381 data = spi_i2s_data_receive(spi_periph);
382
383 if(recv_ptr != RT_NULL)
384 {
385 *recv_ptr++ = data;
386 }
387 }
388 }
389 }
390
391 /* release CS */
392 if(message->cs_release)
393 {
394 rt_pin_write(cs_pin, PIN_HIGH);
395 LOG_D("spi release cs\n");
396 }
397
398 return message->length;
399 };
400
401 /**
402 * Attach the spi device to SPI bus, this function must be used after initialization.
403 */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_base_t cs_pin)404 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
405 {
406 RT_ASSERT(bus_name != RT_NULL);
407 RT_ASSERT(device_name != RT_NULL);
408
409 rt_err_t result;
410 struct rt_spi_device *spi_device;
411
412 /* attach the device to spi bus*/
413 spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
414 RT_ASSERT(spi_device != RT_NULL);
415
416 if(cs_pin != PIN_NONE)
417 {
418 /* initialize the cs pin && select the slave*/
419 rt_pin_mode(cs_pin, PIN_MODE_OUTPUT);
420 rt_pin_write(cs_pin, PIN_HIGH);
421 }
422
423 result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
424
425 if (result != RT_EOK)
426 {
427 LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
428 }
429
430 RT_ASSERT(result == RT_EOK);
431
432 LOG_D("%s attach to %s done", device_name, bus_name);
433
434 return result;
435 }
436
rt_hw_spi_init(void)437 int rt_hw_spi_init(void)
438 {
439 int result = 0;
440 int i;
441
442 for (i = 0; i < sizeof(spi_bus_obj) / sizeof(spi_bus_obj[0]); i++)
443 {
444 spi_bus_obj[i].spi_bus->parent.user_data = (void *)&spi_bus_obj[i];
445
446 result = rt_spi_bus_register(spi_bus_obj[i].spi_bus, spi_bus_obj[i].bus_name, &gd32_spi_ops);
447
448 RT_ASSERT(result == RT_EOK);
449
450 LOG_D("%s bus init done", spi_bus_obj[i].bus_name);
451 }
452
453 return result;
454 }
455
456 INIT_BOARD_EXPORT(rt_hw_spi_init);
457
458 #endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 || BSP_USING_SPI3 || BSP_USING_SPI4*/
459 #endif /* RT_USING_SPI */
460
461