diff --git a/bsp/wch/risc-v/Libraries/ch32_drivers/SConscript b/bsp/wch/risc-v/Libraries/ch32_drivers/SConscript index b17b832dd0..03d2b77732 100644 --- a/bsp/wch/risc-v/Libraries/ch32_drivers/SConscript +++ b/bsp/wch/risc-v/Libraries/ch32_drivers/SConscript @@ -18,6 +18,9 @@ if GetDepend('SOC_RISCV_FAMILY_CH32'): if GetDepend('BSP_USING_DAC'): src += ['drv_dac.c'] + if GetDepend('BSP_USING_I2C'): + src += ['drv_i2c.c'] + if GetDepend('BSP_USING_SOFT_I2C'): src += ['drv_soft_i2c.c'] diff --git a/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.c b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.c new file mode 100644 index 0000000000..7d6f58a92d --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-4-1 IceBear003 the first version + */ + +#include "board.h" +#include "drv_i2c.h" + +#ifdef BSP_USING_HWI2C + +#define LOG_TAG "drv.hwi2c" +#include "drv_log.h" + +#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) +#error "Please define at least one BSP_USING_I2Cx" +/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +#define TIMEOUT 0xFF + +#ifdef BSP_USING_I2C1 +struct i2c_bus_device i2c_bus1; +#endif +#ifdef BSP_USING_I2C2 +struct i2c_bus_device i2c_bus2; +#endif + +static int i2c_read(I2C_TypeDef *i2c_periph, + rt_uint16_t addr, + rt_uint8_t flags, + rt_uint16_t len, + rt_uint8_t *buf) +{ + rt_uint16_t try = 0; + while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY)) + if (try++ >= TIMEOUT) return -1; + + I2C_GenerateSTART(i2c_periph, ENABLE); + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5 + if (try++ >= TIMEOUT) return -1; + + if(flags & RT_I2C_ADDR_10BIT) //10-bit address mode + { + rt_uint8_t frame_head = 0xF0 + (addr >> 8) << 1; //11110XX0 + I2C_SendData(i2c_periph, frame_head); //FrameHead + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10)) //EVT9 + if (try++ >= TIMEOUT) return -1; + + I2C_SendData(i2c_periph,0xff & addr); + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EVT6 + if (try++ >= TIMEOUT) return -1; + + I2C_GenerateSTART(i2c_periph, ENABLE); //Sr + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5 + if (try++ >= TIMEOUT) return -1; + + I2C_SendData(i2c_periph,frame_head); //Resend FrameHead + } + else + { + I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Receiver); + } + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) //EVT6 + if (try++ >= TIMEOUT) return -1; + + while(len-- > 0) + { + + try = 0; + while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_RXNE)) //Got ACK For the Last Byte + if (try++ >= TIMEOUT) return -1; + + *(buf++)=I2C_ReceiveData(i2c_periph); + } + + I2C_GenerateSTOP(i2c_periph, ENABLE); +} + +static int i2c_write(I2C_TypeDef *i2c_periph, + rt_uint16_t addr, + rt_uint8_t flags, + rt_uint8_t *buf, + rt_uint16_t len) +{ + rt_uint16_t try = 0; + while (I2C_GetFlagStatus(i2c_periph, I2C_FLAG_BUSY)) + if (try++ >= TIMEOUT) return -1; + + I2C_GenerateSTART(i2c_periph, ENABLE); + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_SELECT)) //EVT5 + if (try++ >= TIMEOUT) return -1; + + if(flags & RT_I2C_ADDR_10BIT) //10-bit address mode + { + I2C_SendData(i2c_periph,0xF0 + (addr >> 8) << 1); //FrameHead 11110XX0 + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_MODE_ADDRESS10)) //EVT9 + if (try++ >= TIMEOUT) return -1; + + I2C_SendData(i2c_periph,0xff & addr); + } + else //7-bit address mode + { + I2C_Send7bitAddress(i2c_periph, addr << 1, I2C_Direction_Transmitter); + } + + try = 0; + while (!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EVT6 + if (try++ >= TIMEOUT) return -1; + + //Missing Evt8_1 (No definition) + + while(len-- > 0) + { + try = 0; + while (!I2C_GetFlagStatus(i2c_periph, I2C_FLAG_TXE)) //Got ACK For the Last Byte + if (try++ >= TIMEOUT) return -1; + + I2C_SendData(i2c_periph,*(buf++)); + } + + try = 0; + while(!I2C_CheckEvent(i2c_periph, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //Last byte sent successfully + if (try++ >= TIMEOUT) return -1; + + I2C_GenerateSTOP(i2c_periph, ENABLE); +} + +rt_size_t i2c_master_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct rt_i2c_msg *msg; + struct i2c_bus_device *i2c_bus_dev; + rt_uint32_t index; + + i2c_bus_dev = (struct i2c_bus_device *)bus; + + for (index = 0; index < num; index++) + { + msg = &msgs[index]; + if (msg->flags & RT_I2C_RD) + { + i2c_read(i2c_bus_dev->periph, + msg->addr, + msg->flags, + msg->len, + msg->buf); + } + else + { + i2c_write(i2c_bus_dev->periph, + msg->addr, + msg->flags, + msg->buf, + msg->len); + } + } + + return index; +} + +static const struct rt_i2c_bus_device_ops ch32_i2c_ops = +{ + .master_xfer = i2c_master_xfer, + .slave_xfer = RT_NULL, //Not Used in i2c_core? + .i2c_bus_control = RT_NULL +}; + +int rt_hw_i2c_init(struct i2c_config *config = &{5000, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit}) +{ + int result = RT_EOK; + + GPIO_InitTypeDef GPIO_InitStructure = {0}; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; + + I2C_InitTypeDef I2C_InitTSturcture = {0}; + I2C_StructInit(&I2C_InitTSturcture); + I2C_InitTSturcture.I2C_ClockSpeed = config->clock_speed; + I2C_InitTSturcture.I2C_DutyCycle = config->duty_cycle; + I2C_InitTSturcture.I2C_OwnAddress1 = config->own_address; + I2C_InitTSturcture.I2C_Ack = config->enable_ack ? I2C_Ack_Enable : I2C_Ack_Disable; + I2C_InitTSturcture.I2C_AcknowledgedAddress = config->is_7_bit_address ? I2C_AcknowledgedAddress_7bit : I2C_AcknowledgedAddress_10bit; + + +#ifdef BSP_USING_I2C1 + + i2c_bus1.periph = I2C1; + + //Clock & IO Initialization + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); + + //I2C Initialization Config + I2C_Init(I2C1, &I2C_InitTSturcture); + I2C_Cmd(I2C1, ENABLE); + + //Hook to RT-Thread + i2c_bus1.parent.ops = &ch32_i2c_ops; + result += rt_i2c_bus_device_register(&i2c_bus1.parent, "i2c1"); + +#endif + +#ifdef BSP_USING_I2C2 + + i2c_bus2.periph = I2C2; + + //Clock & IO Initialization + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + //I2C Initialization Config + I2C_Init(I2C2, &I2C_InitTSturcture); + I2C_Cmd(I2C2, ENABLE); + + //Hook to RT-Thread + i2c_bus2.parent.ops = &ch32_i2c_ops; + result += rt_i2c_bus_device_register(&i2c_bus2.parent, "i2c2"); + +#endif + + return result; +} + +#endif //BSP_USING_HWI2C \ No newline at end of file diff --git a/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.h b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.h new file mode 100644 index 0000000000..31c314c600 --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch32_drivers/drv_i2c.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-4-1 IceBear003 the first version + */ + +#ifndef __DRV_I2C_H_ +#define __DRV_I2C_H_ + +#include +#include + +struct i2c_bus_device +{ + struct rt_i2c_bus_device parent; + I2C_TypeDef *periph; +}; + +struct i2c_config +{ + rt_uint32_t clock_speed; + uint16_t duty_cycle; + uint16_t own_address; + uint8_t enable_ack; + uint8_t is_7_bit_address; +}; + +struct i2c_config i2c_default_conf={5000, I2C_Mode_I2C, I2C_DutyCycle_2, 0, I2C_Ack_Disable, I2C_AcknowledgedAddress_7bit}; + +int rt_hw_i2c_init(struct i2c_config *config); + +#endif \ No newline at end of file diff --git a/bsp/wch/risc-v/ch32v307v-r1/board/Kconfig b/bsp/wch/risc-v/ch32v307v-r1/board/Kconfig index 7a24302d4c..19e9199239 100644 --- a/bsp/wch/risc-v/ch32v307v-r1/board/Kconfig +++ b/bsp/wch/risc-v/ch32v307v-r1/board/Kconfig @@ -121,6 +121,21 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_I2C + bool "Enable I2C" + select RT_USING_I2C + + if BSP_USING_I2C + config BSP_USING_I2C1 + bool "Enable I2C1" + default n + + config BSP_USING_I2C2 + bool "Enable I2C2" + default n + + endif + menuconfig BSP_USING_SOFT_I2C bool "Enable I2C Bus" select RT_USING_I2C