Skip to content

Commit 03a9418

Browse files
committed
add hardware i2c support
1 parent d82dd71 commit 03a9418

File tree

7 files changed

+284
-5
lines changed

7 files changed

+284
-5
lines changed

bsp/gd32/arm/gd32e230-lckfb/.ci/attachconfig/ci.attachconfig.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ hw_drv_onchip.i2c0:
2222
kconfig:
2323
- CONFIG_BSP_USING_I2C0=y
2424
- CONFIG_BSP_I2C0_SCL_PIN=22
25-
- CONFIG_BSP_I2C0_SDA_PIN=23
25+
- CONFIG_BSP_I2C0_SDA_PIN=23
26+
hw_drv_onchip.i2c1:
27+
kconfig:
28+
- CONFIG_BSP_USING_HW_I2C=y
29+
- CONFIG_BSP_USING_HW_I2C1=y
30+
- CONFIG_BSP_HW_I2C1_CLOCK_SPEED=400000

bsp/gd32/arm/gd32e230-lckfb/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,18 @@
3636
| :--- | :---: | :--- |
3737
| GPIO | 支持 | PAx, PBx... |
3838
| UART | 支持 | USART0, USART1 |
39+
| I2C | 支持 | I2C0, I2C1 硬件I2C |
3940
| **扩展模块** | **支持情况** | **备注** |
4041
| 暂无 | 暂不支持 | 暂不支持 |
4142

43+
### 补充说明
44+
45+
I2C 引脚分配:
46+
- **I2C0**: SCL(PA9), SDA(PA10)
47+
- **I2C1**: SCL(PB10), SDA(PB11)
48+
默认速率400KHz,可以配置调整。
49+
50+
4251
## 使用说明
4352

4453
使用说明分为如下两个章节:
@@ -95,7 +104,7 @@ pyocd flash -t gd32e230c8t6 rtthread.bin
95104
4. 输入 `scons -j12` 编译。
96105

97106
## 注意事项
98-
1. GD32E230资源受限,虽然通过调整参数极限运行msh,但是意义不大,建议关闭。
107+
1. GD32E230资源受限,虽然通过调整参数可以运行msh,但是意义不大,建议关闭。
99108
2. **GPIOA-13****GPIOA-14** 默认用于 SWD 调试下载功能,建议不要配置为其它功能,否则将可能导致无法正常下载和调试。
100109

101110
## 联系人信息

bsp/gd32/arm/gd32e230-lckfb/board/Kconfig

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,35 @@ menu "On-chip Peripheral Drivers"
146146
select RT_USING_I2C
147147
default n
148148
if BSP_USING_HW_I2C
149-
config BSP_USING_I2C0
149+
config BSP_USING_HW_I2C0
150150
bool "Enable I2C0"
151151
default y
152152

153-
config BSP_USING_I2C1
153+
config BSP_HW_I2C0_CLOCK_SPEED
154+
int "I2C0 Clock Speed (Hz)"
155+
depends on BSP_USING_HW_I2C0
156+
range 100000 1000000
157+
default 400000
158+
help
159+
Set the I2C0 clock speed in Hz.
160+
Standard mode: 100000 (100KHz)
161+
Fast mode: 400000 (400KHz)
162+
Fast mode plus: 1000000 (1MHz)
163+
164+
config BSP_USING_HW_I2C1
154165
bool "Enable I2C1"
155166
default n
167+
168+
config BSP_HW_I2C1_CLOCK_SPEED
169+
int "I2C1 Clock Speed (Hz)"
170+
depends on BSP_USING_HW_I2C1
171+
range 100000 1000000
172+
default 400000
173+
help
174+
Set the I2C1 clock speed in Hz.
175+
Standard mode: 100000 (100KHz)
176+
Fast mode: 400000 (400KHz)
177+
Fast mode plus: 1000000 (1MHz)
156178
endif
157179
menuconfig BSP_USING_I2C0
158180
bool "Enable I2C0 BUS (software simulation)"

bsp/gd32/arm/gd32e230-lckfb/rtconfig.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
/* end of rt_strnlen options */
6363
/* end of klibc options */
64-
#define RT_NAME_MAX 8
64+
#define RT_NAME_MAX 16
6565
#define RT_CPUS_NR 1
6666
#define RT_ALIGN_SIZE 8
6767
#define RT_THREAD_PRIORITY_32

bsp/gd32/arm/libraries/gd32_drivers/SConscript

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ if GetDepend(['RT_USING_SERIAL']):
2323
if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
2424
if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'):
2525
src += ['drv_soft_i2c.c']
26+
27+
# add i2c hard drivers.
28+
if GetDepend(['RT_USING_I2C']):
29+
if GetDepend('BSP_USING_HW_I2C0') or GetDepend('BSP_USING_HW_I2C1'):
30+
src += ['drv_hw_i2c.c']
2631

2732
# add spi drivers.
2833
if GetDepend('RT_USING_SPI'):
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
*/
7+
8+
#include "drv_hw_i2c.h"
9+
10+
#ifdef RT_USING_I2C
11+
12+
#define LOG_TAG "drv.hw_i2c"
13+
#include <rtdbg.h>
14+
15+
#if !defined(BSP_USING_HW_I2C0) && !defined(BSP_USING_HW_I2C1)
16+
#error "Please define at least one BSP_USING_HW_I2Cx in board.h"
17+
#endif
18+
19+
static const struct gd32_i2c_config i2c_configs[] =
20+
{
21+
#ifdef BSP_USING_HW_I2C0
22+
{
23+
.i2c_periph = I2C0,
24+
.periph_clk = RCU_I2C0,
25+
26+
.scl_clk = RCU_GPIOA,
27+
.scl_port = GPIOA,
28+
.scl_pin = GPIO_PIN_9,
29+
.scl_af = GPIO_AF_4,
30+
.sda_clk = RCU_GPIOA,
31+
.sda_port = GPIOA,
32+
.sda_pin = GPIO_PIN_10,
33+
.sda_af = GPIO_AF_4,
34+
35+
.i2c_clock_hz = BSP_HW_I2C0_CLOCK_SPEED,
36+
.device_name = "i2c0",
37+
},
38+
#endif
39+
#ifdef BSP_USING_HW_I2C1
40+
{
41+
.i2c_periph = I2C1,
42+
.periph_clk = RCU_I2C1,
43+
44+
.scl_clk = RCU_GPIOB,
45+
.scl_port = GPIOB,
46+
.scl_pin = GPIO_PIN_10,
47+
.scl_af = GPIO_AF_1,
48+
.sda_clk = RCU_GPIOB,
49+
.sda_port = GPIOB,
50+
.sda_pin = GPIO_PIN_11,
51+
.sda_af = GPIO_AF_1,
52+
.i2c_clock_hz = BSP_HW_I2C1_CLOCK_SPEED,
53+
.device_name = "i2c1",
54+
},
55+
#endif
56+
};
57+
58+
static struct gd32_i2c i2c_objs[sizeof(i2c_configs) / sizeof(i2c_configs[0])];
59+
60+
static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
61+
struct rt_i2c_msg msgs[],
62+
rt_uint32_t num)
63+
{
64+
struct gd32_i2c *i2c_dev = rt_container_of(bus, struct gd32_i2c, parent);
65+
const struct gd32_i2c_config *config = i2c_dev->config;
66+
rt_uint32_t i2c_periph = config->i2c_periph;
67+
rt_uint32_t i;
68+
rt_err_t ret = RT_EOK;
69+
70+
while (i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY));
71+
72+
for (i = 0; i < num; i++)
73+
{
74+
struct rt_i2c_msg *msg = &msgs[i];
75+
rt_uint16_t slave_addr = msg->addr;
76+
77+
i2c_start_on_bus(i2c_periph);
78+
while (!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND));
79+
80+
if (msg->flags & RT_I2C_RD)
81+
{
82+
i2c_master_addressing(i2c_periph, slave_addr << 1, I2C_RECEIVER);
83+
}
84+
else
85+
{
86+
i2c_master_addressing(i2c_periph, slave_addr << 1, I2C_TRANSMITTER);
87+
}
88+
89+
while (!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND));
90+
i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND);
91+
92+
if (msg->flags & RT_I2C_RD)
93+
{
94+
if (msg->len == 1)
95+
{
96+
i2c_ack_config(i2c_periph, I2C_ACK_DISABLE);
97+
}
98+
else
99+
{
100+
i2c_ack_config(i2c_periph, I2C_ACK_ENABLE);
101+
}
102+
103+
for (rt_uint32_t j = 0; j < msg->len; j++)
104+
{
105+
if (j == msg->len - 1)
106+
{
107+
i2c_ack_config(i2c_periph, I2C_ACK_DISABLE);
108+
}
109+
while (!i2c_flag_get(i2c_periph, I2C_FLAG_RBNE));
110+
msg->buf[j] = i2c_data_receive(i2c_periph);
111+
}
112+
}
113+
else
114+
{
115+
for (rt_uint32_t j = 0; j < msg->len; j++)
116+
{
117+
while (!i2c_flag_get(i2c_periph, I2C_FLAG_TBE));
118+
i2c_data_transmit(i2c_periph, msg->buf[j]);
119+
}
120+
while (!i2c_flag_get(i2c_periph, I2C_FLAG_BTC));
121+
}
122+
123+
if (!(msg->flags & RT_I2C_NO_STOP))
124+
{
125+
i2c_stop_on_bus(i2c_periph);
126+
while(i2c_flag_get(i2c_periph, I2C_FLAG_STPDET));
127+
}
128+
}
129+
130+
return (ret == RT_EOK) ? i : ret;
131+
}
132+
133+
134+
static const struct rt_i2c_bus_device_ops gd32_i2c_ops =
135+
{
136+
.master_xfer = gd32_i2c_master_xfer,
137+
.slave_xfer = RT_NULL,
138+
.i2c_bus_control = RT_NULL,
139+
};
140+
141+
int rt_hw_i2c_init(void)
142+
{
143+
rt_size_t obj_num = sizeof(i2c_objs) / sizeof(struct gd32_i2c);
144+
rt_err_t result;
145+
146+
for (int i = 0; i < obj_num; i++)
147+
{
148+
struct gd32_i2c *i2c_obj = &i2c_objs[i];
149+
const struct gd32_i2c_config *config = &i2c_configs[i];
150+
151+
i2c_obj->config = config;
152+
153+
i2c_obj->i2c_clock_hz = config->i2c_clock_hz;
154+
155+
rcu_periph_clock_enable(config->periph_clk);
156+
rcu_periph_clock_enable(config->scl_clk);
157+
rcu_periph_clock_enable(config->sda_clk);
158+
159+
gpio_af_set(config->scl_port, config->scl_af, config->scl_pin);
160+
gpio_mode_set(config->scl_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->scl_pin);
161+
gpio_output_options_set(config->scl_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->scl_pin);
162+
163+
gpio_af_set(config->sda_port, config->sda_af, config->sda_pin);
164+
gpio_mode_set(config->sda_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->sda_pin);
165+
gpio_output_options_set(config->sda_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->sda_pin);
166+
167+
i2c_deinit(config->i2c_periph);
168+
i2c_clock_config(config->i2c_periph, i2c_obj->i2c_clock_hz, I2C_DTCY_2);
169+
i2c_mode_addr_config(config->i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
170+
i2c_enable(config->i2c_periph);
171+
i2c_ack_config(config->i2c_periph, I2C_ACK_ENABLE);
172+
173+
i2c_obj->parent.ops = &gd32_i2c_ops;
174+
result = rt_i2c_bus_device_register(&i2c_obj->parent, config->device_name);
175+
RT_ASSERT(result == RT_EOK);
176+
177+
LOG_D("%s bus init success, clock %dHz.", config->device_name, i2c_obj->i2c_clock_hz);
178+
}
179+
180+
return RT_EOK;
181+
}
182+
183+
INIT_BOARD_EXPORT(rt_hw_i2c_init);
184+
185+
#endif
186+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef __DRV_HW_I2C_H__
8+
#define __DRV_HW_I2C_H__
9+
10+
#include <rtthread.h>
11+
#include <rthw.h>
12+
#include <rtdevice.h>
13+
#include <board.h>
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
struct gd32_i2c_config
20+
{
21+
rt_uint32_t i2c_periph;
22+
rcu_periph_enum periph_clk;
23+
24+
rcu_periph_enum scl_clk;
25+
rt_uint32_t scl_port;
26+
rt_uint32_t scl_pin;
27+
rt_uint32_t scl_af;
28+
29+
rcu_periph_enum sda_clk;
30+
rt_uint32_t sda_port;
31+
rt_uint32_t sda_pin;
32+
rt_uint32_t sda_af;
33+
34+
rt_uint32_t i2c_clock_hz; /* I2C clock frequency in Hz */
35+
const char *device_name;
36+
};
37+
38+
struct gd32_i2c
39+
{
40+
struct rt_i2c_bus_device parent;
41+
const struct gd32_i2c_config *config;
42+
rt_uint32_t i2c_clock_hz;
43+
};
44+
45+
int rt_hw_i2c_init(void);
46+
47+
#ifdef __cplusplus
48+
}
49+
#endif
50+
51+
#endif /* __DRV_HW_I2C_H__ */
52+

0 commit comments

Comments
 (0)