From 0c55c4d3ed8a2b2f15e1652321634403bf249efa Mon Sep 17 00:00:00 2001 From: Shicheng Chu <1468559561@qq.com> Date: Sat, 29 Apr 2023 12:40:15 +0800 Subject: [PATCH] [bsp][bl] add drv_soft_i2c (#7406) --- bsp/bouffalo_lab/libraries/rt_drivers/Kconfig | 52 ++++- .../libraries/rt_drivers/SConscript | 4 +- .../libraries/rt_drivers/drv_soft_i2c.c | 211 ++++++++++++++++++ .../libraries/rt_drivers/drv_soft_i2c.h | 44 ++++ 4 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c create mode 100644 bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.h diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig index 4d8a297515..c4ef0fd855 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig +++ b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig @@ -174,6 +174,56 @@ menu "General Drivers Configuration" config BSP_USING_ON_CHIP_FLASH bool "Enable on-chip FLASH" default n - + menu "General Purpose I2C" + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1" + default n + select BSP_USING_I2C + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + choice + prompt "I2C1 SCL PIN" + default I2C1_SCL_USING_GPIO4 if BSP_USING_BL60X + default I2C1_SCL_USING_GPIO10 if BSP_USING_BL61X + default I2C1_SCL_USING_GPIO08 if BSP_USING_BL70X + default I2C1_SCL_USING_GPIO20 if BSP_USING_BL808 + + config I2C1_SCL_USING_GPIO0 + bool "GPIO_0" + config I2C1_SCL_USING_GPIO4 + bool "GPIO_4" + config I2C1_SCL_USING_GPIO8 + bool "GPIO_8" + config I2C1_SCL_USING_GPIO10 + bool "GPIO_10" + config I2C1_SCL_USING_GPIO20 + bool "GPIO_20" + + endchoice + choice + prompt "I2C1 SDA PIN" + default I2C1_SDA_USING_GPIO3 if BSP_USING_BL60X + default I2C1_SDA_USING_GPIO11 if BSP_USING_BL61X + default I2C1_SDA_USING_GPIO7 if BSP_USING_BL70X + default I2C1_SDA_USING_GPIO21 if BSP_USING_BL808 + + config I2C1_SDA_USING_GPIO1 + bool "GPIO_1" + config I2C1_SDA_USING_GPIO3 + bool "GPIO_3" + config I2C1_SDA_USING_GPIO7 + bool "GPIO_7" + config I2C1_SDA_USING_GPIO11 + bool "GPIO_11" + config I2C1_SDA_USING_GPIO21 + bool "GPIO_21" + + endchoice + endif + endmenu + endmenu diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript index c898047412..8eb236373b 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript +++ b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript @@ -9,8 +9,8 @@ CPPPATH = [cwd] if GetDepend('BSP_USING_GPIO'): src += ['drv_gpio.c'] -if GetDepend('BSP_USING_I2C'): - src += ['drv_i2c.c'] +if GetDepend('RT_USING_I2C'): + src += ['drv_soft_i2c.c'] if GetDepend('BSP_USING_ADC'): src += ['drv_adc.c'] diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c new file mode 100644 index 0000000000..0d20c1d119 --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023/04/15 chushicheng first version + */ + +#include "drv_soft_i2c.h" +#include "bflb_gpio.h" +#include "bflb_common.h" + +#ifdef RT_USING_I2C +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "DRV.I2C" + +#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 + +// uart1 +#ifdef I2C1_SCL_USING_GPIO0 +#define BSP_I2C1_SCL_PIN GPIO_PIN_0 +#elif defined(I2C1_SCL_USING_GPIO4) +#define BSP_I2C1_SCL_PIN GPIO_PIN_4 +#elif defined(I2C1_SCL_USING_GPIO8) +#define BSP_I2C1_SCL_PIN GPIO_PIN_8 +#elif defined(I2C1_SCL_USING_GPIO10) +#define BSP_I2C1_SCL_PIN GPIO_PIN_10 +#elif defined(I2C1_SCL_USING_GPIO20) +#define BSP_I2C1_SCL_PIN GPIO_PIN_20 +#endif + +#ifdef I2C1_SDA_USING_GPIO1 +#define BSP_I2C1_SDA_PIN GPIO_PIN_1 +#elif defined(I2C1_SDA_USING_GPIO3) +#define BSP_I2C1_SDA_PIN GPIO_PIN_3 +#elif defined(I2C1_SDA_USING_GPIO7) +#define BSP_I2C1_SDA_PIN GPIO_PIN_7 +#elif defined(I2C1_SDA_USING_GPIO11) +#define BSP_I2C1_SDA_PIN GPIO_PIN_11 +#elif defined(I2C1_SDA_USING_GPIO21) +#define BSP_I2C1_SDA_PIN GPIO_PIN_21 +#endif + +static const struct bl_soft_i2c_config soft_i2c_config[] = +{ +#ifdef BSP_USING_I2C1 + I2C1_BUS_CONFIG, +#endif +}; + +static struct bl_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; + +/** + * This function initializes the i2c pin. + * + * @param bl i2c dirver class. + */ +static void bl_i2c_gpio_init(struct bl_i2c *i2c) +{ + struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)i2c->ops.data; + + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD); + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD); + + rt_pin_write(cfg->scl, PIN_HIGH); + rt_pin_write(cfg->sda, PIN_HIGH); +} + +/** + * This function sets the sda pin. + * + * @param bl config class. + * @param The sda pin state. + */ +static void bl_set_sda(void *data, rt_int32_t state) +{ + struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->sda, PIN_HIGH); + } + else + { + rt_pin_write(cfg->sda, PIN_LOW); + } +} + +/** + * This function sets the scl pin. + * + * @param bl config class. + * @param The scl pin state. + */ +static void bl_set_scl(void *data, rt_int32_t state) +{ + struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data; + if (state) + { + rt_pin_write(cfg->scl, PIN_HIGH); + } + else + { + rt_pin_write(cfg->scl, PIN_LOW); + } +} + +/** + * This function gets the sda pin state. + * + * @param The sda pin state. + */ +static rt_int32_t bl_get_sda(void *data) +{ + struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data; + return rt_pin_read(cfg->sda); +} + +/** + * This function gets the scl pin state. + * + * @param The scl pin state. + */ +static rt_int32_t bl_get_scl(void *data) +{ + struct bl_soft_i2c_config* cfg = (struct bl_soft_i2c_config*)data; + return rt_pin_read(cfg->scl); +} + +/** + * The time delay function. + * + * @param microseconds. + */ +static void bl_udelay(rt_uint32_t us) +{ + arch_delay_us(us); +} + +static const struct rt_i2c_bit_ops bl_bit_ops_default = +{ + .data = RT_NULL, + .set_sda = bl_set_sda, + .set_scl = bl_set_scl, + .get_sda = bl_get_sda, + .get_scl = bl_get_scl, + .udelay = bl_udelay, + .delay_us = 1, + .timeout = 100 +}; + +/** + * if i2c is locked, this function will unlock it + * + * @param bl config class + * + * @return RT_EOK indicates successful unlock. + */ +static rt_err_t bl_i2c_bus_unlock(const struct bl_soft_i2c_config *cfg) +{ + rt_int32_t i = 0; + + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + while (i++ < 9) + { + rt_pin_write(cfg->scl, PIN_HIGH); + bl_udelay(100); + rt_pin_write(cfg->scl, PIN_LOW); + bl_udelay(100); + } + } + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +/* I2C initialization function */ +int rt_hw_i2c_init(void) +{ + rt_err_t result; + + for (rt_size_t i = 0; i < sizeof(i2c_obj) / sizeof(struct bl_i2c); i++) + { + i2c_obj[i].ops = bl_bit_ops_default; + i2c_obj[i].ops.data = (void*)&soft_i2c_config[i]; + i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops; + bl_i2c_gpio_init(&i2c_obj[i]); + result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name); + RT_ASSERT(result == RT_EOK); + bl_i2c_bus_unlock(&soft_i2c_config[i]); + + LOG_D("software simulation %s init done, pin scl: %d, pin sda %d", + soft_i2c_config[i].bus_name, + soft_i2c_config[i].scl, + soft_i2c_config[i].sda); + } + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_i2c_init); + +#endif /* RT_USING_I2C */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.h b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.h new file mode 100644 index 0000000000..f25488c4e3 --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023/04/15 chushicheng first version + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include +#include +#include + +/* bl i2c dirver class */ +struct bl_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device i2c2_bus; +}; + +/* bl config class */ +struct bl_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; + +#ifdef BSP_USING_I2C1 +#define I2C1_BUS_CONFIG \ + { \ + .scl = BSP_I2C1_SCL_PIN, \ + .sda = BSP_I2C1_SDA_PIN, \ + .bus_name = "i2c1", \ + } +#endif + +int rt_hw_i2c_init(void); + +#endif