Skip to content

Commit 3a84509

Browse files
committed
[drv] Add GD32V SPI driver and ST7735 (LCD) driver (3-wire SPI)
- Add common SPI and SD card device drivers from upstream
1 parent b4cfb41 commit 3a84509

File tree

18 files changed

+3929
-107
lines changed

18 files changed

+3929
-107
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=RT-Thread
2-
version=0.8.0
2+
version=0.8.1
33
author=onelife <[email protected]>, Bernard Xiong <[email protected]>
44
maintainer=onelife <[email protected]>
55
sentence=Real Time Operating System porting for Arduino SAM and SAMD boards

src/bsp/LonganNano/drv_spi.c

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
/***************************************************************************//**
2+
* @file drv_tick.cpp
3+
* @brief Arduino RT-Thread library RISC-V tick driver
4+
* @author onelife <onelife.real[at]gmail.com>
5+
******************************************************************************/
6+
#include "components/drivers/include/rtdevice.h"
7+
8+
#if defined(BOARD_SIPEED_LONGAN_NANO) && CONFIG_USING_DRIVER_SPI
9+
10+
#include "bsp/bsp.h"
11+
12+
#if !CONFIG_USING_SPI0 && !CONFIG_USING_SPI1
13+
# error "No CONFIG_USING_SPIx enabled"
14+
#endif
15+
16+
/***************************************************************************//**
17+
* @addtogroup LonganNano
18+
* @{
19+
******************************************************************************/
20+
21+
/* Private define ------------------------------------------------------------*/
22+
#ifdef RT_USING_ULOG
23+
# ifdef BSP_SPI_DEBUG
24+
# define LOG_LVL LOG_LVL_DBG
25+
# else
26+
# define LOG_LVL LOG_LVL_INFO
27+
# endif
28+
# define LOG_TAG "SPI"
29+
# include "components/utilities/ulog/ulog.h"
30+
#else /* RT_USING_ULOG */
31+
# define LOG_E(format, args...) rt_kprintf(format "\n", ##args)
32+
# define LOG_W LOG_E
33+
# ifdef BSP_SPI_DEBUG
34+
# define LOG_I(format, args...) rt_kprintf(format "\n", ##args)
35+
# else
36+
# define LOG_I(format, args...)
37+
# endif
38+
# define LOG_D LOG_I
39+
# define LOG_HEX(format, args...)
40+
#endif /* RT_USING_ULOG */
41+
42+
/* Private typedef -----------------------------------------------------------*/
43+
struct bsp_spi_contex {
44+
char *name;
45+
rcu_clock_freq_enum clk_src;
46+
rt_uint32_t chn;
47+
rt_uint32_t spi_base;
48+
rt_uint32_t spi_clk;
49+
rt_uint32_t gpio_clk;
50+
rt_uint32_t gpio_port;
51+
rt_uint32_t mosi_pin;
52+
rt_uint32_t miso_pin;
53+
rt_uint32_t sck_pin;
54+
rt_uint32_t cs_pin;
55+
// IRQn_Type irq;
56+
};
57+
58+
enum bsp_spi_channel {
59+
#if CONFIG_USING_SPI0
60+
SPI_CH0 = 0,
61+
#endif
62+
#if CONFIG_USING_SPI1
63+
SPI_CH1 = 1,
64+
#endif
65+
SPI_CH_NUM = CONFIG_USING_SPI0 + CONFIG_USING_SPI1,
66+
};
67+
68+
/* Private function prototypes -----------------------------------------------*/
69+
static rt_err_t op_configure(struct rt_spi_device* dev,
70+
struct rt_spi_configuration* cfg);
71+
static rt_uint32_t op_xfer(struct rt_spi_device* dev,
72+
struct rt_spi_message* msg);
73+
74+
/* Private constants ---------------------------------------------------------*/
75+
76+
/* Private variables ---------------------------------------------------------*/
77+
static struct rt_spi_bus spi_dev[SPI_CH_NUM];
78+
79+
static struct bsp_spi_contex spi_ctx[SPI_CH_NUM] = {
80+
#if CONFIG_USING_SPI0
81+
{
82+
"SPI0",
83+
CK_APB2,
84+
SPI_CH0,
85+
SPI0,
86+
RCU_SPI0,
87+
RCU_GPIOA,
88+
GPIOA,
89+
GPIO_PIN_7,
90+
GPIO_PIN_6,
91+
GPIO_PIN_5,
92+
GPIO_PIN_4,
93+
},
94+
#endif
95+
#if CONFIG_USING_SPI1
96+
{
97+
"SPI1",
98+
CK_APB1,
99+
SPI_CH1,
100+
SPI1,
101+
RCU_SPI1,
102+
RCU_GPIOB,
103+
GPIOB,
104+
GPIO_PIN_15,
105+
GPIO_PIN_14,
106+
GPIO_PIN_13,
107+
GPIO_PIN_12,
108+
},
109+
#endif
110+
};
111+
112+
static struct rt_spi_ops spi_ops = {
113+
op_configure,
114+
op_xfer,
115+
};
116+
117+
/* Private functions ---------------------------------------------------------*/
118+
static rt_err_t op_configure(struct rt_spi_device* dev,
119+
struct rt_spi_configuration* cfg) {
120+
struct bsp_spi_contex *ctx;
121+
spi_parameter_struct init;
122+
rt_uint32_t clk;
123+
124+
RT_ASSERT(dev != RT_NULL);
125+
RT_ASSERT(cfg != RT_NULL);
126+
ctx = (struct bsp_spi_contex *)dev->bus->parent.user_data
127+
RT_ASSERT(ctx != RT_NULL);
128+
LOG_D("[SPI%d] op_configure", ctx->chn);
129+
130+
spi_i2s_deinit(ctx->spi_base);
131+
132+
/* NOTE: currently only support master mode */
133+
init.device_mode = SPI_MASTER;
134+
135+
if (cfg->mode & RT_SPI_3WIRE) {
136+
init.trans_mode = SPI_TRANSMODE_BDTRANSMIT;
137+
} else {
138+
init.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
139+
}
140+
141+
if (cfg->data_width <= 8) {
142+
init.frame_size = SPI_FRAMESIZE_8BIT;
143+
} else if(cfg->data_width <= 16) {
144+
init.frame_size = SPI_FRAMESIZE_16BIT;
145+
} else {
146+
LOG_W("[SPI%d E] data_width (%d)", ctx->chn, cfg->data_width);
147+
return RT_EINVAL;
148+
}
149+
150+
/* NOTE: currently only support software CS */
151+
init.nss = SPI_NSS_SOFT;
152+
153+
if (cfg->mode & RT_SPI_MSB) {
154+
init.endian = SPI_ENDIAN_MSB;
155+
} else {
156+
init.endian = SPI_ENDIAN_LSB;
157+
}
158+
159+
switch (cfg->mode & (RT_SPI_CPOL | RT_SPI_CPHA)) {
160+
case RT_SPI_MODE_0:
161+
init.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
162+
break;
163+
case RT_SPI_MODE_1:
164+
init.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
165+
break;
166+
case RT_SPI_MODE_2:
167+
init.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
168+
break;
169+
case RT_SPI_MODE_3:
170+
init.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
171+
break;
172+
default:
173+
break;
174+
}
175+
176+
if (0 == ctx->chn) {
177+
clk = rcu_clock_freq_get(CK_APB2);
178+
} else {
179+
clk = rcu_clock_freq_get(CK_APB1);
180+
}
181+
LOG_D("[SPI%d] APB freq: %7d\n", ctx->chn, clk);
182+
LOG_D("[SPI%d] MAX freq: %7d\n", ctx->chn, cfg->max_hz);
183+
if (cfg->max_hz >= clk >> 1) {
184+
init.prescale = SPI_PSC_2;
185+
} else if (cfg->max_hz >= clk >> 2) {
186+
init.prescale = SPI_PSC_4;
187+
} else if (cfg->max_hz >= clk >> 3) {
188+
init.prescale = SPI_PSC_8;
189+
} else if (cfg->max_hz >= clk >> 4) {
190+
init.prescale = SPI_PSC_16;
191+
} else if (cfg->max_hz >= clk >> 5) {
192+
init.prescale = SPI_PSC_32;
193+
} else if (cfg->max_hz >= clk >> 6) {
194+
init.prescale = SPI_PSC_64;
195+
} else if (cfg->max_hz >= clk >> 7) {
196+
init.prescale = SPI_PSC_128;
197+
} else {
198+
init.prescale = SPI_PSC_256;
199+
}
200+
201+
spi_init(ctx->spi_base, &init);
202+
spi_crc_off(ctx->spi_base);
203+
spi_enable(ctx->spi_base);
204+
205+
return RT_EOK;
206+
};
207+
208+
static rt_uint32_t op_xfer(struct rt_spi_device* dev,
209+
struct rt_spi_message* msg) {
210+
struct bsp_spi_contex *ctx;
211+
struct rt_spi_configuration *cfg;
212+
rt_uint8_t mode3 = 0;
213+
rt_uint32_t i;
214+
const rt_uint16_t dummy = 0xffff;
215+
216+
RT_ASSERT(dev != NULL);
217+
RT_ASSERT(msg != NULL);
218+
ctx = (struct bsp_spi_contex *)dev->bus->parent.user_data;
219+
cfg = &dev->config;
220+
221+
if (RT_NULL != msg->send_buf) {
222+
if (cfg->mode & RT_SPI_3WIRE) {
223+
spi_bidirectional_transfer_config(ctx->spi_base,
224+
SPI_BIDIRECTIONAL_TRANSMIT);
225+
mode3 = 1;
226+
LOG_D("[SPI%d] 3TX (%d)", ctx->chn, msg->length);
227+
} else {
228+
LOG_D("[SPI%d] TX (%d)", ctx->chn, msg->length);
229+
}
230+
}
231+
if (RT_NULL != msg->recv_buf) {
232+
if ((mode3 == 0) && (cfg->mode & RT_SPI_3WIRE)) {
233+
spi_bidirectional_transfer_config(ctx->spi_base,
234+
SPI_BIDIRECTIONAL_RECEIVE);
235+
mode3 = 2;
236+
LOG_D("[SPI%d] 3RX (%d)", ctx->chn, msg->length);
237+
} else {
238+
LOG_D("[SPI%d] RX (%d)", ctx->chn, msg->length);
239+
}
240+
}
241+
242+
if (msg->cs_take) {
243+
LOG_D("[SPI%d] CS enable", ctx->chn);
244+
gpio_bit_reset(ctx->gpio_port, ctx->cs_pin);
245+
}
246+
247+
for (i = 0; i < msg->length; i++) {
248+
if (2 != mode3) {
249+
while (RESET == spi_i2s_flag_get(ctx->spi_base, SPI_FLAG_TBE)) {
250+
asm volatile ("nop");
251+
}
252+
if (RT_NULL == msg->send_buf) {
253+
spi_i2s_data_transmit(ctx->spi_base, dummy);
254+
} else if (cfg->data_width <= 8) {
255+
spi_i2s_data_transmit(ctx->spi_base,
256+
(rt_uint16_t)((rt_uint8_t *)msg->send_buf)[i]);
257+
} else {
258+
spi_i2s_data_transmit(ctx->spi_base,
259+
((rt_uint16_t *)msg->send_buf)[i]);
260+
}
261+
}
262+
263+
if (1 != mode3) {
264+
while (RESET == spi_i2s_flag_get(ctx->spi_base, SPI_FLAG_RBNE)) {
265+
asm volatile ("nop");
266+
}
267+
if (RT_NULL == msg->recv_buf) {
268+
(void)spi_i2s_data_receive(ctx->spi_base);
269+
} else if (cfg->data_width <= 8) {
270+
((rt_uint8_t *)msg->recv_buf)[i] = (rt_uint8_t)spi_i2s_data_receive(ctx->spi_base);
271+
} else {
272+
((rt_uint16_t *)msg->recv_buf)[i] = spi_i2s_data_receive(ctx->spi_base);
273+
}
274+
}
275+
}
276+
277+
if (msg->cs_release) {
278+
LOG_D("[SPI%d] CS disable", ctx->chn);
279+
gpio_bit_set(ctx->gpio_port, ctx->cs_pin);
280+
}
281+
282+
return msg->length;
283+
};
284+
285+
/* Public functions ----------------------------------------------------------*/
286+
rt_err_t bsp_hw_spi_init(void) {
287+
uint8_t i;
288+
rt_err_t ret;
289+
290+
ret = RT_ERROR;
291+
for (i = 0; i < SPI_CH_NUM; i++) {
292+
/* enable clock */
293+
rcu_periph_clock_enable(spi_ctx[i].gpio_clk);
294+
rcu_periph_clock_enable(spi_ctx[i].spi_clk);
295+
/* setup GPIO */
296+
gpio_init(spi_ctx[i].gpio_port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ,
297+
spi_ctx[i].mosi_pin | spi_ctx[i].miso_pin | spi_ctx[i].sck_pin);
298+
gpio_init(spi_ctx[i].gpio_port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
299+
spi_ctx[i].cs_pin);
300+
/* register device */
301+
spi_dev[i].parent.user_data = (void *)&spi_ctx[i];
302+
ret = rt_spi_bus_register(
303+
&spi_dev[i],
304+
spi_ctx[i].name,
305+
&spi_ops);
306+
RT_ASSERT(ret == RT_EOK);
307+
LOG_D("[SPI%d] h/w init ok", spi_ctx[i].chn);
308+
}
309+
310+
return ret;
311+
}
312+
INIT_BOARD_EXPORT(bsp_hw_spi_init);
313+
314+
/***************************************************************************//**
315+
* @}
316+
******************************************************************************/
317+
318+
#endif /* defined(BOARD_SIPEED_LONGAN_NANO) && CONFIG_USING_DRIVER_SPI */

src/bsp/LonganNano/drv_spi.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/***************************************************************************//**
2+
* @file drv_spi.h
3+
* @brief Arduino RT-Thread library RISC-V SPI driver header
4+
* @author onelife <onelife.real[at]gmail.com>
5+
******************************************************************************/
6+
#ifndef __LONGAN_NANO_DRV_SPI_H__
7+
#define __LONGAN_NANO_DRV_SPI_H__
8+
9+
/* Includes ------------------------------------------------------------------*/
10+
/* Exported defines ----------------------------------------------------------*/
11+
#define SPI_MAX_SPEED (27000000)
12+
13+
/* Exported types ------------------------------------------------------------*/
14+
/* Exported constants --------------------------------------------------------*/
15+
16+
/* Exported functions ------------------------------------------------------- */
17+
rt_err_t bsp_hw_spi_init(void);
18+
19+
#endif // __LONGAN_NANO_DRV_SPI_H__

0 commit comments

Comments
 (0)