diff --git a/bsp/gd32/arm/gd32e230-lckfb/.ci/attachconfig/ci.attachconfig.yml b/bsp/gd32/arm/gd32e230-lckfb/.ci/attachconfig/ci.attachconfig.yml index 506885b13f7..216b8f01901 100644 --- a/bsp/gd32/arm/gd32e230-lckfb/.ci/attachconfig/ci.attachconfig.yml +++ b/bsp/gd32/arm/gd32e230-lckfb/.ci/attachconfig/ci.attachconfig.yml @@ -22,4 +22,9 @@ hw_drv_onchip.i2c0: kconfig: - CONFIG_BSP_USING_I2C0=y - CONFIG_BSP_I2C0_SCL_PIN=22 - - CONFIG_BSP_I2C0_SDA_PIN=23 \ No newline at end of file + - CONFIG_BSP_I2C0_SDA_PIN=23 +hw_drv_onchip.i2c1: + kconfig: + - CONFIG_BSP_USING_HW_I2C=y + - CONFIG_BSP_USING_HW_I2C1=y + - CONFIG_BSP_HW_I2C1_CLOCK_SPEED=400000 \ No newline at end of file diff --git a/bsp/gd32/arm/gd32e230-lckfb/README.md b/bsp/gd32/arm/gd32e230-lckfb/README.md index 9c5164d67f0..8eda3f3f7c8 100644 --- a/bsp/gd32/arm/gd32e230-lckfb/README.md +++ b/bsp/gd32/arm/gd32e230-lckfb/README.md @@ -36,9 +36,18 @@ | :--- | :---: | :--- | | GPIO | 支持 | PAx, PBx... | | UART | 支持 | USART0, USART1 | +| I2C | 支持 | I2C0, I2C1 硬件I2C | | **扩展模块** | **支持情况** | **备注** | | 暂无 | 暂不支持 | 暂不支持 | +### 补充说明 + +I2C 引脚分配: +- **I2C0**: SCL(PA9), SDA(PA10) +- **I2C1**: SCL(PB10), SDA(PB11) +默认速率400KHz,可以配置调整。 + + ## 使用说明 使用说明分为如下两个章节: @@ -95,7 +104,7 @@ pyocd flash -t gd32e230c8t6 rtthread.bin 4. 输入 `scons -j12` 编译。 ## 注意事项 -1. GD32E230资源受限,虽然通过调整参数极限运行msh,但是意义不大,建议关闭。 +1. GD32E230资源受限,虽然通过调整参数可以运行msh,但是意义不大,建议关闭。 2. **GPIOA-13** 和 **GPIOA-14** 默认用于 SWD 调试下载功能,建议不要配置为其它功能,否则将可能导致无法正常下载和调试。 ## 联系人信息 diff --git a/bsp/gd32/arm/gd32e230-lckfb/board/Kconfig b/bsp/gd32/arm/gd32e230-lckfb/board/Kconfig index d8a53a95625..a1a63c5981e 100644 --- a/bsp/gd32/arm/gd32e230-lckfb/board/Kconfig +++ b/bsp/gd32/arm/gd32e230-lckfb/board/Kconfig @@ -146,13 +146,35 @@ menu "On-chip Peripheral Drivers" select RT_USING_I2C default n if BSP_USING_HW_I2C - config BSP_USING_I2C0 + config BSP_USING_HW_I2C0 bool "Enable I2C0" default y - config BSP_USING_I2C1 + config BSP_HW_I2C0_CLOCK_SPEED + int "I2C0 Clock Speed (Hz)" + depends on BSP_USING_HW_I2C0 + range 100000 1000000 + default 400000 + help + Set the I2C0 clock speed in Hz. + Standard mode: 100000 (100KHz) + Fast mode: 400000 (400KHz) + Fast mode plus: 1000000 (1MHz) + + config BSP_USING_HW_I2C1 bool "Enable I2C1" default n + + config BSP_HW_I2C1_CLOCK_SPEED + int "I2C1 Clock Speed (Hz)" + depends on BSP_USING_HW_I2C1 + range 100000 1000000 + default 400000 + help + Set the I2C1 clock speed in Hz. + Standard mode: 100000 (100KHz) + Fast mode: 400000 (400KHz) + Fast mode plus: 1000000 (1MHz) endif menuconfig BSP_USING_I2C0 bool "Enable I2C0 BUS (software simulation)" diff --git a/bsp/gd32/arm/gd32e230-lckfb/rtconfig.h b/bsp/gd32/arm/gd32e230-lckfb/rtconfig.h index 9fc76ea3276..85fcd0192bb 100644 --- a/bsp/gd32/arm/gd32e230-lckfb/rtconfig.h +++ b/bsp/gd32/arm/gd32e230-lckfb/rtconfig.h @@ -61,7 +61,7 @@ /* end of rt_strnlen options */ /* end of klibc options */ -#define RT_NAME_MAX 8 +#define RT_NAME_MAX 16 #define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 diff --git a/bsp/gd32/arm/libraries/gd32_drivers/SConscript b/bsp/gd32/arm/libraries/gd32_drivers/SConscript index cb2193d0f16..dca1ac329f4 100644 --- a/bsp/gd32/arm/libraries/gd32_drivers/SConscript +++ b/bsp/gd32/arm/libraries/gd32_drivers/SConscript @@ -23,6 +23,11 @@ if GetDepend(['RT_USING_SERIAL']): if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'): src += ['drv_soft_i2c.c'] + + # add i2c hard drivers. +if GetDepend(['RT_USING_I2C']): + if GetDepend('BSP_USING_HW_I2C0') or GetDepend('BSP_USING_HW_I2C1'): + src += ['drv_hw_i2c.c'] # add spi drivers. if GetDepend('RT_USING_SPI'): diff --git a/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.c b/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.c new file mode 100644 index 00000000000..7424c8fa335 --- /dev/null +++ b/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "drv_hw_i2c.h" + +#ifdef RT_USING_I2C + +#define LOG_TAG "drv.hw_i2c" +#include + +#if !defined(BSP_USING_HW_I2C0) && !defined(BSP_USING_HW_I2C1) +#error "Please define at least one BSP_USING_HW_I2Cx in board.h" +#endif + +static const struct gd32_i2c_config i2c_configs[] = +{ +#ifdef BSP_USING_HW_I2C0 + { + .i2c_periph = I2C0, + .periph_clk = RCU_I2C0, + + .scl_clk = RCU_GPIOA, + .scl_port = GPIOA, + .scl_pin = GPIO_PIN_9, + .scl_af = GPIO_AF_4, + .sda_clk = RCU_GPIOA, + .sda_port = GPIOA, + .sda_pin = GPIO_PIN_10, + .sda_af = GPIO_AF_4, + + .i2c_clock_hz = BSP_HW_I2C0_CLOCK_SPEED, + .device_name = "i2c0", + }, +#endif +#ifdef BSP_USING_HW_I2C1 + { + .i2c_periph = I2C1, + .periph_clk = RCU_I2C1, + + .scl_clk = RCU_GPIOB, + .scl_port = GPIOB, + .scl_pin = GPIO_PIN_10, + .scl_af = GPIO_AF_1, + .sda_clk = RCU_GPIOB, + .sda_port = GPIOB, + .sda_pin = GPIO_PIN_11, + .sda_af = GPIO_AF_1, + .i2c_clock_hz = BSP_HW_I2C1_CLOCK_SPEED, + .device_name = "i2c1", + }, +#endif +}; + +static struct gd32_i2c i2c_objs[sizeof(i2c_configs) / sizeof(i2c_configs[0])]; + +static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct gd32_i2c *i2c_dev = rt_container_of(bus, struct gd32_i2c, parent); + const struct gd32_i2c_config *config = i2c_dev->config; + rt_uint32_t i2c_periph = config->i2c_periph; + rt_uint32_t i; + rt_err_t ret = RT_EOK; + + while (i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY)); + + for (i = 0; i < num; i++) + { + struct rt_i2c_msg *msg = &msgs[i]; + rt_uint16_t slave_addr = msg->addr; + + i2c_start_on_bus(i2c_periph); + while (!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND)); + + if (msg->flags & RT_I2C_RD) + { + i2c_master_addressing(i2c_periph, slave_addr << 1, I2C_RECEIVER); + } + else + { + i2c_master_addressing(i2c_periph, slave_addr << 1, I2C_TRANSMITTER); + } + + while (!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)); + i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); + + if (msg->flags & RT_I2C_RD) + { + if (msg->len == 1) + { + i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); + } + else + { + i2c_ack_config(i2c_periph, I2C_ACK_ENABLE); + } + + for (rt_uint32_t j = 0; j < msg->len; j++) + { + if (j == msg->len - 1) + { + i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); + } + while (!i2c_flag_get(i2c_periph, I2C_FLAG_RBNE)); + msg->buf[j] = i2c_data_receive(i2c_periph); + } + } + else + { + for (rt_uint32_t j = 0; j < msg->len; j++) + { + while (!i2c_flag_get(i2c_periph, I2C_FLAG_TBE)); + i2c_data_transmit(i2c_periph, msg->buf[j]); + } + while (!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)); + } + + if (!(msg->flags & RT_I2C_NO_STOP)) + { + i2c_stop_on_bus(i2c_periph); + while(i2c_flag_get(i2c_periph, I2C_FLAG_STPDET)); + } + } + + return (ret == RT_EOK) ? i : ret; +} + + +static const struct rt_i2c_bus_device_ops gd32_i2c_ops = +{ + .master_xfer = gd32_i2c_master_xfer, + .slave_xfer = RT_NULL, + .i2c_bus_control = RT_NULL, +}; + +int rt_hw_i2c_init(void) +{ + rt_size_t obj_num = sizeof(i2c_objs) / sizeof(struct gd32_i2c); + rt_err_t result; + + for (int i = 0; i < obj_num; i++) + { + struct gd32_i2c *i2c_obj = &i2c_objs[i]; + const struct gd32_i2c_config *config = &i2c_configs[i]; + + i2c_obj->config = config; + + i2c_obj->i2c_clock_hz = config->i2c_clock_hz; + + rcu_periph_clock_enable(config->periph_clk); + rcu_periph_clock_enable(config->scl_clk); + rcu_periph_clock_enable(config->sda_clk); + + gpio_af_set(config->scl_port, config->scl_af, config->scl_pin); + gpio_mode_set(config->scl_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->scl_pin); + gpio_output_options_set(config->scl_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->scl_pin); + + gpio_af_set(config->sda_port, config->sda_af, config->sda_pin); + gpio_mode_set(config->sda_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->sda_pin); + gpio_output_options_set(config->sda_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, config->sda_pin); + + i2c_deinit(config->i2c_periph); + i2c_clock_config(config->i2c_periph, i2c_obj->i2c_clock_hz, I2C_DTCY_2); + i2c_mode_addr_config(config->i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); + i2c_enable(config->i2c_periph); + i2c_ack_config(config->i2c_periph, I2C_ACK_ENABLE); + + i2c_obj->parent.ops = &gd32_i2c_ops; + result = rt_i2c_bus_device_register(&i2c_obj->parent, config->device_name); + RT_ASSERT(result == RT_EOK); + + LOG_D("%s bus init success, clock %dHz.", config->device_name, i2c_obj->i2c_clock_hz); + } + + return RT_EOK; +} + +INIT_BOARD_EXPORT(rt_hw_i2c_init); + +#endif + diff --git a/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.h b/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.h new file mode 100644 index 00000000000..5e83ea5dc2d --- /dev/null +++ b/bsp/gd32/arm/libraries/gd32_drivers/drv_hw_i2c.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DRV_HW_I2C_H__ +#define __DRV_HW_I2C_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct gd32_i2c_config +{ + rt_uint32_t i2c_periph; + rcu_periph_enum periph_clk; + + rcu_periph_enum scl_clk; + rt_uint32_t scl_port; + rt_uint32_t scl_pin; + rt_uint32_t scl_af; + + rcu_periph_enum sda_clk; + rt_uint32_t sda_port; + rt_uint32_t sda_pin; + rt_uint32_t sda_af; + + rt_uint32_t i2c_clock_hz; /* I2C clock frequency in Hz */ + const char *device_name; +}; + +struct gd32_i2c +{ + struct rt_i2c_bus_device parent; + const struct gd32_i2c_config *config; + rt_uint32_t i2c_clock_hz; +}; + +int rt_hw_i2c_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_HW_I2C_H__ */ +