fix(bsp/gd32/arm): 修复gd32硬件i2c驱动

- 硬件i2c主机接收驱动采用方案B,但不支持接收小于3字节,现修复该问题
- 增加方案A。
This commit is contained in:
石鸿超
2026-01-11 19:18:36 +08:00
committed by Rbb666
parent 4851ea2eee
commit a5e991d75c
6 changed files with 231 additions and 186 deletions

View File

@@ -1440,22 +1440,16 @@ CONFIG_BSP_USING_UART0=y
# CONFIG_BSP_USING_UART3 is not set
# CONFIG_BSP_USING_UART4 is not set
# CONFIG_BSP_USING_UART5 is not set
CONFIG_BSP_USING_HARD_I2C=y
CONFIG_BSP_USING_RECEIVING_A=y
# CONFIG_BSP_USING_RECEIVING_B is not set
CONFIG_BSP_USING_HARD_I2C0=y
# CONFIG_BSP_USING_HARD_I2C1 is not set
# CONFIG_BSP_USING_HARD_I2C2 is not set
# CONFIG_BSP_USING_SPI is not set
# CONFIG_BSP_USING_ADC is not set
# CONFIG_BSP_USING_HWTIMER is not set
CONFIG_BSP_USING_PWM=y
CONFIG_BSP_USING_PWM0=y
CONFIG_BSP_USING_PWM1=y
CONFIG_BSP_USING_PWM2=y
CONFIG_BSP_USING_PWM3=y
CONFIG_BSP_USING_PWM4=y
CONFIG_BSP_USING_PWM7=y
CONFIG_BSP_USING_PWM8=y
CONFIG_BSP_USING_PWM9=y
CONFIG_BSP_USING_PWM10=y
CONFIG_BSP_USING_PWM11=y
CONFIG_BSP_USING_PWM12=y
CONFIG_BSP_USING_PWM13=y
# CONFIG_BSP_USING_PWM is not set
# CONFIG_BSP_USING_ONCHIP_RTC is not set
# CONFIG_BSP_USING_WDT is not set
# CONFIG_BSP_USING_SDIO is not set

View File

@@ -232,6 +232,35 @@ menu "On-chip Peripheral Drivers"
default 32
endif
menuconfig BSP_USING_HARD_I2C
bool "Enable I2C"
select RT_USING_I2C
default n
if BSP_USING_HARD_I2C
choice
prompt "Select I2C Receiving Scheme"
default BSP_USING_RECEIVING_A
config BSP_USING_RECEIVING_A
bool "master receiving secheme A --- requires that the software be capable of responding quickly to the 12C event."
config BSP_USING_RECEIVING_B
bool "master receiving secheme B --- don't requires that the software be capable of responding quickly to the 12C event."
endchoice
config BSP_USING_HARD_I2C0
bool "enable hard I2C0"
default n
config BSP_USING_HARD_I2C1
bool "enable hard I2C1"
default n
config BSP_USING_HARD_I2C2
bool "enable hard I2C2"
default n
endif
menuconfig BSP_USING_SPI
bool "Enable SPI BUS"
default n

File diff suppressed because it is too large Load Diff

View File

@@ -338,9 +338,9 @@
<v6Rtti>0</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define>RT_USING_LIBC, HXTAL_VALUE=8000000U, RT_USING_ARMLIBC, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND, GD32F405, __STDC_LIMIT_MACROS</Define>
<Define>RT_USING_LIBC, GD32F405, __RTTHREAD__, USE_STDPERIPH_DRIVER, __CLK_TCK=RT_TICK_PER_SECOND, RT_USING_ARMLIBC, __STDC_LIMIT_MACROS, HXTAL_VALUE=8000000U</Define>
<Undefine></Undefine>
<IncludePath>packages\gd32-arm-cmsis-latest\GD32F4xx\GD\GD32F4xx\Include;packages\gd32-arm-cmsis-latest\GD32F4xx;.;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\drivers\smp_call;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\net\utest;applications;..\..\..\..\components\libc\compilers\common\extension;..\..\..\..\components\libc\posix\io\epoll;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\components\libc\posix\ipc;..\..\..\..\components\drivers\include;packages\gd32-arm-series-latest\GD32F4xx\GD32F4xx_standard_peripheral\Include;..\..\..\..\components\drivers\phy;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;board;..\..\..\..\libcpu\arm\cortex-m4;..\..\..\..\libcpu\arm\common;..\..\..\..\include;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;..\..\..\..\components\finsh;..\..\..\..\components\drivers\include;..\libraries\gd32_drivers;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\io\eventfd</IncludePath>
<IncludePath>applications;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\extension\fcntl\octal;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\posix\ipc;..\..\..\..\components\libc\posix\io\poll;..\..\..\..\components\libc\posix\io\eventfd;board;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\smp_call;..\..\..\..\libcpu\arm\common;..\..\..\..\components\drivers\include;..\..\..\..\libcpu\arm\cortex-m4;packages\gd32-arm-cmsis-latest\GD32F4xx\GD\GD32F4xx\Include;..\..\..\..\components\libc\posix\io\epoll;..\libraries\gd32_drivers;..\..\..\..\components\libc\compilers\common\extension;..\..\..\..\components\net\utest;..\..\..\..\components\drivers\phy;..\..\..\..\include;packages\gd32-arm-cmsis-latest\GD32F4xx;.;..\..\..\..\components\drivers\include;packages\gd32-arm-series-latest\GD32F4xx\GD32F4xx_standard_peripheral\Include;..\..\..\..\components\drivers\include;..\..\..\..\components\drivers\include;..\..\..\..\components\libc\compilers\common\include;..\..\..\..\components\finsh;..\..\..\..\components\drivers\include</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -1406,6 +1406,11 @@
<FileType>1</FileType>
<FilePath>..\libraries\gd32_drivers\drv_gpio.c</FilePath>
</File>
<File>
<FileName>drv_hard_i2c.c</FileName>
<FileType>1</FileType>
<FilePath>..\libraries\gd32_drivers\drv_hard_i2c.c</FilePath>
</File>
<File>
<FileName>drv_hwtimer.c</FileName>
<FileType>1</FileType>
@@ -1426,16 +1431,6 @@
<Group>
<GroupName>Finsh</GroupName>
<Files>
<File>
<FileName>msh_parse.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\msh_parse.c</FilePath>
</File>
<File>
<FileName>shell.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\shell.c</FilePath>
</File>
<File>
<FileName>msh.c</FileName>
<FileType>1</FileType>
@@ -1446,6 +1441,16 @@
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\cmd.c</FilePath>
</File>
<File>
<FileName>shell.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\shell.c</FilePath>
</File>
<File>
<FileName>msh_parse.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\components\finsh\msh_parse.c</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -2297,9 +2302,9 @@
<GroupName>klibc</GroupName>
<Files>
<File>
<FileName>kstring.c</FileName>
<FileName>kerrno.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\kstring.c</FilePath>
<FilePath>..\..\..\..\src\klibc\kerrno.c</FilePath>
</File>
<File>
<FileName>rt_vsscanf.c</FileName>
@@ -2307,9 +2312,9 @@
<FilePath>..\..\..\..\src\klibc\rt_vsscanf.c</FilePath>
</File>
<File>
<FileName>kerrno.c</FileName>
<FileName>kstring.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\..\src\klibc\kerrno.c</FilePath>
<FilePath>..\..\..\..\src\klibc\kstring.c</FilePath>
</File>
<File>
<FileName>kstdio.c</FileName>
@@ -2406,11 +2411,6 @@
<FileType>1</FileType>
<FilePath>packages\gd32-arm-series-latest\GD32F4xx\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c</FilePath>
</File>
<File>
<FileName>gd32f4xx_timer.c</FileName>
<FileType>1</FileType>
<FilePath>.\packages\gd32-arm-series-latest\GD32F4xx\GD32F4xx_standard_peripheral\Source\gd32f4xx_timer.c</FilePath>
</File>
</Files>
</Group>
<Group>

View File

@@ -422,19 +422,9 @@
#define BSP_USING_GPIO
#define BSP_USING_UART
#define BSP_USING_UART0
#define BSP_USING_PWM
#define BSP_USING_PWM0
#define BSP_USING_PWM1
#define BSP_USING_PWM2
#define BSP_USING_PWM3
#define BSP_USING_PWM4
#define BSP_USING_PWM7
#define BSP_USING_PWM8
#define BSP_USING_PWM9
#define BSP_USING_PWM10
#define BSP_USING_PWM11
#define BSP_USING_PWM12
#define BSP_USING_PWM13
#define BSP_USING_HARD_I2C
#define BSP_USING_RECEIVING_A
#define BSP_USING_HARD_I2C0
#define BSP_USING_GD_DBG
/* end of On-chip Peripheral Drivers */

View File

@@ -6,6 +6,8 @@
* Change Logs:
* Date Author Notes
* 2021-12-20 BruceOu the first version
* 2026-01-11 ShiHongchao Fix the I2C master receive mode B software
* flow and add support for mode A
*/
#include "drv_hard_i2c.h"
@@ -112,8 +114,8 @@ static const struct gd32_i2c_bus gd_i2c_config[] = {
RCU_I2C0, RCU_GPIOB, RCU_GPIOB, /* periph clock, scl gpio clock, sda gpio clock */
GPIOB, GPIO_AF_4, GPIO_PIN_6, /* scl port, scl alternate, scl pin */
GPIOB, GPIO_AF_4, GPIO_PIN_7, /* sda port, sda alternate, sda pin */
GPIOB, GPIO_AF_4, GPIO_PIN_8, /* scl port, scl alternate, scl pin */
GPIOB, GPIO_AF_4, GPIO_PIN_9, /* sda port, sda alternate, sda pin */
&i2c0,
"hwi2c0",
@@ -229,13 +231,52 @@ static void gd32_i2c_gpio_init(const struct gd32_i2c_bus *i2c)
static uint8_t gd32_i2c_read(rt_uint32_t i2c_periph, rt_uint8_t *p_buffer, rt_uint16_t data_byte)
{
if (data_byte == 0) return 1;
/* while there is data to be read */
#ifdef BSP_USING_RECEIVING_A
/*
In single-byte reception, disable ACK because the master needs to send
NACK after receiving the first byte,indicating no more data will be
received, then immediately send the stop condition
*/
if(data_byte == 1)
{
/* disable acknowledge */
i2c_ack_config(i2c_periph, I2C_ACK_DISABLE);
/* send a stop condition to I2C bus */
i2c_stop_on_bus(i2c_periph);
}
#endif
/* while there is data to be read */
while(data_byte)
{
#if defined (SOC_SERIES_GD32F5xx) || defined (SOC_SERIES_GD32F4xx)
if(IS_I2C_LEGACY(i2c_periph))
{
#ifdef BSP_USING_RECEIVING_A
/*
After receiving the second-to-last byte, ACK should be disabled
and STOP should be set, to ensure that NACK is sent after receiving
the last byte and the stop condition is transmitted
*/
if(2 == data_byte)
{
/* wait until BTC bit is set */
while(!i2c_flag_get(i2c_periph, I2C_FLAG_RBNE));
/* disable acknowledge */
i2c_ack_config(i2c_periph, I2C_ACK_DISABLE);
/* send a stop condition to I2C bus */
i2c_stop_on_bus(i2c_periph);
}
#elif defined(BSP_USING_RECEIVING_B)
/*
For 3-byte reception: Wait for byte transfer completion, then
disable ACK so NACK is automatically sent after receiving the
last byte
For 2-byte reception: Wait for byte transfer completion, then
send stop condition to ensure direct stop after receiving the
last byte instead of sending ACK
*/
if(3 == data_byte)
{
/* wait until BTC bit is set */
@@ -243,14 +284,16 @@ static uint8_t gd32_i2c_read(rt_uint32_t i2c_periph, rt_uint8_t *p_buffer, rt_ui
/* disable acknowledge */
i2c_ack_config(i2c_periph, I2C_ACK_DISABLE);
}
if(2 == data_byte)
else if(2 == data_byte)
{
/* wait until BTC bit is set */
while(!i2c_flag_get(i2c_periph, I2C_FLAG_BTC));
/* send a stop condition to I2C bus */
i2c_stop_on_bus(i2c_periph);
}
#else
#error "Please select the receiving secheme."
#endif
/* wait until RBNE bit is set */
if(i2c_flag_get(i2c_periph, I2C_FLAG_RBNE))
{
@@ -379,11 +422,18 @@ static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_
{
i2c_stop_on_bus(gd32_i2c->i2c_periph);
}
/* enable acknowledge */
/* enable acknowledge */
i2c_ack_config(gd32_i2c->i2c_periph, I2C_ACK_ENABLE);
/* i2c master sends start signal only when the bus is idle */
/* i2c master sends start signal only when the bus is idle */
while(i2c_flag_get(gd32_i2c->i2c_periph, I2C_FLAG_I2CBSY));
/* send the start signal */
#ifdef BSP_USING_RECEIVING_B
/* */
if(msg->len == 2)
{
i2c_ackpos_config(gd32_i2c->i2c_periph, I2C_ACKPOS_NEXT);
}
#endif
/* send the start signal */
i2c_start_on_bus(gd32_i2c->i2c_periph);
/* i2c master sends START signal successfully */
while(!i2c_flag_get(gd32_i2c->i2c_periph, I2C_FLAG_SBSEND));
@@ -391,14 +441,26 @@ static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_
i2c_master_addressing(gd32_i2c->i2c_periph, msg->addr, I2C_RECEIVER);
while(!i2c_flag_get(gd32_i2c->i2c_periph, I2C_FLAG_ADDSEND));
/* address flag set means i2c slave sends ACK */
#ifdef BSP_USING_RECEIVING_B
if(msg->len <= 2)
{
i2c_ack_config(gd32_i2c->i2c_periph, I2C_ACK_DISABLE);
}
#endif
/* address flag set means i2c slave sends ACK */
i2c_flag_clear(gd32_i2c->i2c_periph, I2C_FLAG_ADDSEND);
#ifdef BSP_USING_RECEIVING_B
if(msg->len == 1)
{
i2c_stop_on_bus(gd32_i2c->i2c_periph);
}
#endif
}else {
/* configure slave address */
/* configure slave address */
while(i2c_flag_get(gd32_i2c->i2c_periph, I2C_FLAG_I2CBSY));
//i2c_transfer_byte_number_config(gd32_i2c->i2c_periph, w_total_byte);
/* send a start condition to I2C bus */
//i2c_transfer_byte_number_config(gd32_i2c->i2c_periph, w_total_byte);
/* send a start condition to I2C bus */
i2c_start_on_bus(gd32_i2c->i2c_periph);
while(!i2c_flag_get(gd32_i2c->i2c_periph, I2C_FLAG_SBSEND));