Skip to content

Commit 8a4625a

Browse files
committed
add hardware i2c support
1 parent d82dd71 commit 8a4625a

File tree

5 files changed

+246
-3
lines changed

5 files changed

+246
-3
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@ 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_I2C0=22

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,11 @@ 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_USING_HW_I2C1
154154
bool "Enable I2C1"
155155
default n
156156
endif

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: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "drv_hw_i2c.h"
8+
9+
#ifdef RT_USING_I2C
10+
11+
#define LOG_TAG "drv.hw_i2c"
12+
#include <rtdbg.h>
13+
14+
#if !defined(BSP_USING_HW_I2C0) && !defined(BSP_USING_HW_I2C1)
15+
#error "Please define at least one BSP_USING_HW_I2Cx in board.h"
16+
#endif
17+
18+
static const struct gd32_i2c_config i2c_configs[] =
19+
{
20+
#ifdef BSP_USING_HW_I2C0
21+
{
22+
.i2c_periph = I2C0,
23+
.periph_clk = RCU_I2C0,
24+
25+
.scl_clk = RCU_GPIOA,
26+
.scl_port = GPIOA,
27+
.scl_pin = GPIO_PIN_9,
28+
.scl_af = GPIO_AF_1,
29+
.sda_clk = RCU_GPIOA,
30+
.sda_port = GPIOA,
31+
.sda_pin = GPIO_PIN_10,
32+
.sda_af = GPIO_AF_1,
33+
34+
.device_name = "i2c0",
35+
},
36+
#endif
37+
#ifdef BSP_USING_HW_I2C1
38+
{
39+
.i2c_periph = I2C1,
40+
.periph_clk = RCU_I2C1,
41+
42+
.scl_clk = RCU_GPIOB,
43+
.scl_port = GPIOB,
44+
.scl_pin = GPIO_PIN_10,
45+
.scl_af = GPIO_AF_1,
46+
.sda_clk = RCU_GPIOB,
47+
.sda_port = GPIOB,
48+
.sda_pin = GPIO_PIN_11,
49+
.sda_af = GPIO_AF_1,
50+
.device_name = "i2c1",
51+
},
52+
#endif
53+
};
54+
};
55+
56+
static struct gd32_i2c i2c_objs[sizeof(i2c_configs) / sizeof(i2c_configs[0])];
57+
58+
static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus,
59+
struct rt_i2c_msg msgs[],
60+
rt_uint32_t num)
61+
{
62+
struct gd32_i2c *i2c_dev = rt_container_of(bus, struct gd32_i2c, parent);
63+
const struct gd32_i2c_config *config = i2c_dev->config;
64+
rt_uint32_t i2c_periph = config->i2c_periph;
65+
rt_uint32_t i;
66+
rt_err_t ret = RT_EOK;
67+
68+
/* 等待总线空闲 */
69+
while (i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY));
70+
71+
for (i = 0; i < num; i++)
72+
{
73+
struct rt_i2c_msg *msg = &msgs[i];
74+
rt_uint16_t slave_addr = msg->addr;
75+
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+
/*
154+
* TODO: 从 board.h 获取时钟频率, 此处为示例
155+
* 您可以在板级配置中定义 I2C0_CLOCK_HZ, I2C1_CLOCK_HZ
156+
*/
157+
i2c_obj->i2c_clock_hz = 100000; // 默认为 100KHz
158+
159+
rcu_periph_clock_enable(config->periph_clk);
160+
rcu_periph_clock_enable(config->scl_clk);
161+
rcu_periph_clock_enable(config->sda_clk);
162+
163+
gpio_af_set(config->scl_port, config->scl_af, config->scl_pin);
164+
gpio_mode_set(config->scl_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->scl_pin);
165+
gpio_output_options_set(config->scl_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->scl_pin);
166+
167+
gpio_af_set(config->sda_port, config->sda_af, config->sda_pin);
168+
gpio_mode_set(config->sda_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->sda_pin);
169+
gpio_output_options_set(config->sda_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->sda_pin);
170+
171+
i2c_deinit(config->i2c_periph);
172+
i2c_clock_config(config->i2c_periph, i2c_obj->i2c_clock_hz, I2C_DTCY_2);
173+
i2c_mode_addr_config(config->i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
174+
i2c_enable(config->i2c_periph);
175+
i2c_ack_config(config->i2c_periph, I2C_ACK_ENABLE);
176+
177+
i2c_obj->parent.ops = &gd32_i2c_ops;
178+
result = rt_i2c_bus_device_register(&i2c_obj->parent, config->device_name);
179+
RT_ASSERT(result == RT_EOK);
180+
181+
LOG_D("%s bus init success, clock %dHz.", config->device_name, i2c_obj->i2c_clock_hz);
182+
}
183+
184+
return RT_EOK;
185+
}
186+
187+
INIT_BOARD_EXPORT(rt_hw_i2c_init);
188+
189+
#endif
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#ifndef __DRV_HW_I2C_H__
2+
#define __DRV_HW_I2C_H__
3+
4+
#include <rtthread.h>
5+
#include <rthw.h>
6+
#include <rtdevice.h>
7+
#include <board.h>
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
struct gd32_i2c_config
14+
{
15+
rt_uint32_t i2c_periph;
16+
rcu_periph_enum periph_clk;
17+
18+
rcu_periph_enum scl_clk;
19+
rt_uint32_t scl_port;
20+
rt_uint32_t scl_pin;
21+
rt_uint32_t scl_af;
22+
23+
rcu_periph_enum sda_clk;
24+
rt_uint32_t sda_port;
25+
rt_uint32_t sda_pin;
26+
rt_uint32_t sda_af;
27+
28+
const char *device_name;
29+
};
30+
31+
/* GD32 硬件 I2C 总线设备结构体 */
32+
struct gd32_i2c
33+
{
34+
struct rt_i2c_bus_device parent;
35+
const struct gd32_i2c_config *config;
36+
rt_uint32_t i2c_clock_hz;
37+
};
38+
39+
int rt_hw_i2c_init(void);
40+
41+
#ifdef __cplusplus
42+
}
43+
#endif
44+
45+
#endif /* __DRV_HW_I2C_H__ */

0 commit comments

Comments
 (0)