From 876f2be14c2c5802dd558598dfa5b689b805391d Mon Sep 17 00:00:00 2001 From: wumingzi <62127946+1078249029@users.noreply.github.com> Date: Tue, 10 Dec 2024 08:44:43 +0800 Subject: [PATCH] [bsp][ESP32C3] support soft i2c and rt_hw_us_delay --- .../.ci/attachconfig/ci.attachconfig.yml | 12 +- bsp/ESP32_C3/drivers/Kconfig | 23 +- bsp/ESP32_C3/drivers/SConscript | 3 + bsp/ESP32_C3/drivers/board.c | 34 ++- bsp/ESP32_C3/drivers/board.h | 10 +- bsp/ESP32_C3/drivers/drv_gpio.c | 15 +- bsp/ESP32_C3/drivers/drv_gpio.h | 4 +- bsp/ESP32_C3/drivers/drv_hw_i2c.c | 4 +- bsp/ESP32_C3/drivers/drv_sw_i2c.c | 199 ++++++++++++++++++ bsp/ESP32_C3/drivers/drv_sw_i2c.h | 34 +++ 10 files changed, 320 insertions(+), 18 deletions(-) create mode 100644 bsp/ESP32_C3/drivers/drv_sw_i2c.c create mode 100644 bsp/ESP32_C3/drivers/drv_sw_i2c.h diff --git a/bsp/ESP32_C3/.ci/attachconfig/ci.attachconfig.yml b/bsp/ESP32_C3/.ci/attachconfig/ci.attachconfig.yml index 9b9d4b78bd..af6fbb3d8d 100644 --- a/bsp/ESP32_C3/.ci/attachconfig/ci.attachconfig.yml +++ b/bsp/ESP32_C3/.ci/attachconfig/ci.attachconfig.yml @@ -15,7 +15,17 @@ devices.i2c: kconfig: - CONFIG_RT_USING_I2C=y - CONFIG_BSP_USING_I2C=y - - CONFIG_BSP_USING_I2C0=y +devices.hwi2c: + depends: + - devices.i2c + kconfig: + - CONFIG_BSP_USING_HW_I2C=y +devices.swi2c: + depends: + - devices.i2c + kconfig: + - CONFIG_BSP_USING_SW_I2C=y + - CONFIG_BSP_USING_SW_I2C0=y devices.spi: kconfig: - CONFIG_RT_USING_SPI=y diff --git a/bsp/ESP32_C3/drivers/Kconfig b/bsp/ESP32_C3/drivers/Kconfig index e9d4b0d04d..2d6c4326e9 100644 --- a/bsp/ESP32_C3/drivers/Kconfig +++ b/bsp/ESP32_C3/drivers/Kconfig @@ -72,9 +72,28 @@ menu "On-chip Peripheral Drivers" default n select RT_USING_I2C if BSP_USING_I2C - config BSP_USING_I2C0 - bool "Enable I2C0" + menuconfig BSP_USING_HW_I2C + bool "Enable HardWare I2C" default n + + menuconfig BSP_USING_SW_I2C + bool "Enable SoftWare I2C" + default n + if BSP_USING_SW_I2C + config BSP_USING_SW_I2C0 + bool "Enable SoftWare I2C0" + default n + if BSP_USING_SW_I2C0 + config BSP_SW_I2C0_SDA_PIN + int "SWI2C0 sda pin number" + range 0 21 + default 18 + config BSP_SW_I2C0_SCL_PIN + int "SWI2C0 scl pin number" + range 0 21 + default 19 + endif + endif endif menuconfig BSP_USING_SPI diff --git a/bsp/ESP32_C3/drivers/SConscript b/bsp/ESP32_C3/drivers/SConscript index 76e5d7a517..55e9a09d1d 100644 --- a/bsp/ESP32_C3/drivers/SConscript +++ b/bsp/ESP32_C3/drivers/SConscript @@ -17,6 +17,9 @@ if GetDepend('BSP_USING_ADC'): if GetDepend('BSP_USING_I2C'): src += ['drv_hw_i2c.c'] + +if GetDepend('BSP_USING_SW_I2C'): + src += ['drv_sw_i2c.c'] if GetDepend('BSP_USING_PWM'): src += ['drv_pwm.c'] diff --git a/bsp/ESP32_C3/drivers/board.c b/bsp/ESP32_C3/drivers/board.c index fe82129bc1..2556ec1b8b 100644 --- a/bsp/ESP32_C3/drivers/board.c +++ b/bsp/ESP32_C3/drivers/board.c @@ -1,14 +1,16 @@ /* - * Copyright (c) 2021-2022, RT-Thread Development Team + * Copyright (c) 2021-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-02 supperthomas first version + * 2024-12-08 wumingzi support rt_hw_us_delay */ #include +#include "rttypes.h" #include "hal/systimer_hal.h" #include "hal/systimer_ll.h" #include "esp_private/panic_internal.h" @@ -16,6 +18,8 @@ #include "esp_private/periph_ctrl.h" #include "esp_intr_alloc.h" #include "esp_attr.h" +#include "esp_timer.h" +#include "driver/gptimer.h" static systimer_hal_context_t systimer_hal; IRAM_ATTR void rt_SysTickIsrHandler(void *arg) @@ -57,3 +61,31 @@ void rt_hw_board_init(void) rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif } + +static gptimer_handle_t gptimer_hw_us = NULL; + +static int delay_us_init(void) +{ + gptimer_config_t timer_config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1 * 1000 * 1000, /* 1MHz, 1 tick = 1us*/ + }; + ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer_hw_us)); + ESP_ERROR_CHECK(gptimer_enable(gptimer_hw_us)); + return RT_EOK; +} +INIT_DEVICE_EXPORT(delay_us_init); + +void rt_hw_us_delay(rt_uint32_t us) +{ + uint64_t count = 0; + ESP_ERROR_CHECK(gptimer_start(gptimer_hw_us)); + ESP_ERROR_CHECK(gptimer_set_raw_count(gptimer_hw_us, 0)); + /* Retrieve the timestamp at anytime*/ + while(count < (uint64_t)us) + { + ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer_hw_us, &count)); + } + ESP_ERROR_CHECK(gptimer_stop(gptimer_hw_us)); +} \ No newline at end of file diff --git a/bsp/ESP32_C3/drivers/board.h b/bsp/ESP32_C3/drivers/board.h index 1f152ced85..d9a6655dc8 100644 --- a/bsp/ESP32_C3/drivers/board.h +++ b/bsp/ESP32_C3/drivers/board.h @@ -1,27 +1,27 @@ /* - * Copyright (c) 2021-2022, RT-Thread Development Team + * Copyright (c) 2021-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-02 supperthomas first version + * 2024-12-08 wumingzi support rt_hw_us_delay */ #ifndef __BOARD_H__ #define __BOARD_H__ #include +#include "rttypes.h" #ifdef __cplusplus extern "C" { #endif - void rt_hw_board_init(void); +void rt_hw_us_delay(rt_uint32_t us); #ifdef __cplusplus } #endif - -#endif - +#endif \ No newline at end of file diff --git a/bsp/ESP32_C3/drivers/drv_gpio.c b/bsp/ESP32_C3/drivers/drv_gpio.c index 4a4aa978ff..77721db22a 100644 --- a/bsp/ESP32_C3/drivers/drv_gpio.c +++ b/bsp/ESP32_C3/drivers/drv_gpio.c @@ -1,12 +1,12 @@ /* - * Copyright (c) 2021-2022, RT-Thread Development Team + * Copyright (c) 2021-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-06-03 supperthomas first version - * + * 2024-12-08 wumingzi support open drain mode for soft i2c */ #include @@ -37,9 +37,14 @@ static void mcu_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode) io_conf.pull_down_en = 0; io_conf.pull_up_en = 0; gpio_config(&io_conf); - if (mode == PIN_MODE_OUTPUT) + switch (mode) { - gpio_set_direction(pin, GPIO_MODE_OUTPUT); + case PIN_MODE_INPUT: + gpio_set_direction(pin, GPIO_MODE_INPUT); + case PIN_MODE_OUTPUT: + gpio_set_direction(pin, GPIO_MODE_OUTPUT); + case PIN_MODE_OUTPUT_OD: + gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT_OD); } /*TODO:set gpio out put mode */ } @@ -84,4 +89,4 @@ int rt_hw_pin_init(void) } INIT_BOARD_EXPORT(rt_hw_pin_init); -#endif /* RT_USING_PIN */ +#endif /* RT_USING_PIN */ \ No newline at end of file diff --git a/bsp/ESP32_C3/drivers/drv_gpio.h b/bsp/ESP32_C3/drivers/drv_gpio.h index 01edcc41fd..ea9d1b0f6a 100644 --- a/bsp/ESP32_C3/drivers/drv_gpio.h +++ b/bsp/ESP32_C3/drivers/drv_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, RT-Thread Development Team + * Copyright (c) 2021-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -18,4 +18,4 @@ int rt_hw_pin_init(void); #endif -#endif /* __DRV_GPIO_H__ */ +#endif /* __DRV_GPIO_H__ */ \ No newline at end of file diff --git a/bsp/ESP32_C3/drivers/drv_hw_i2c.c b/bsp/ESP32_C3/drivers/drv_hw_i2c.c index 1597039eaa..27f2486341 100644 --- a/bsp/ESP32_C3/drivers/drv_hw_i2c.c +++ b/bsp/ESP32_C3/drivers/drv_hw_i2c.c @@ -7,13 +7,13 @@ * Date Author Notes *2023-03-28 Zxy first version */ -#ifdef RT_USING_I2C + #include "drv_hw_i2c.h" #include "driver/i2c.h"//bsp/ESP32_C3/packages/ESP-IDF-latest/components/driver/include/driver/i2c.h #include "hal/i2c_types.h"//bsp/ESP32_C3/packages/ESP-IDF-latest/tools/mocks/hal/include/hal/i2c_types.h #include "esp_err.h" //#include "portmacro.h"//bsp/ESP32_C3/packages/FreeRTOS_Wrapper-latest/FreeRTOS/portable/rt-thread/portmacro.h - +#ifdef BSP_USING_HW_I2C struct esp32_i2c { struct rt_i2c_bus_device bus; diff --git a/bsp/ESP32_C3/drivers/drv_sw_i2c.c b/bsp/ESP32_C3/drivers/drv_sw_i2c.c new file mode 100644 index 0000000000..fbfed4d71d --- /dev/null +++ b/bsp/ESP32_C3/drivers/drv_sw_i2c.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2006-2024 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-12-07 wumingzi first version + */ +#include +#include +#define LOG_TAG "drv.i2c" +#ifdef RT_USING_I2C +#ifdef BSP_USING_SW_I2C +#include "rthw.h" +#include "rttypes.h" +#include +#include "driver/gpio.h" +#include "drv_sw_i2c.h" + +#if defined(BSP_USING_SW_I2C0) +#define SW_I2C0_BUS_CONFIG \ + { \ + .scl = BSP_SW_I2C0_SCL_PIN, \ + .sda = BSP_SW_I2C0_SDA_PIN, \ + .bus_name = "i2c0", \ + } +#endif + +static const struct esp32c3_soft_i2c_config soft_i2c_config[] = +{ +#if defined(BSP_USING_SW_I2C0) + SW_I2C0_BUS_CONFIG, +#endif +}; + +static struct esp32c3_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; + +/** + * @brief This function initializes the i2c pin. + * @param i2c + * @retval None + */ +static void esp32c3_i2c_gpio_init(struct esp32c3_i2c *i2c) +{ + struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)i2c->ops.data; + rt_pin_mode(cfg->scl, PIN_MODE_OUTPUT_OD); + rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD); + + gpio_set_pull_mode(cfg->sda, GPIO_FLOATING); + gpio_set_pull_mode(cfg->scl, GPIO_FLOATING); + + gpio_set_level(cfg->scl, PIN_HIGH); + gpio_set_level(cfg->sda, PIN_HIGH); +} + +/** + * @brief This function sets the sda pin. + * @param data, state + * @retval None + */ +static void esp32c3_set_sda(void *data, rt_int32_t state) +{ + struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data; + /*rt_pin_mode(cfg->sda, PIN_MODE_OUTPUT_OD);*/ + if (state) + { + gpio_set_level(cfg->sda, PIN_HIGH); + } + else + { + gpio_set_level(cfg->sda, PIN_LOW); + } +} + +/** + * @brief This function sets the scl pin. + * @param data, state + * @retval None + */ +static void esp32c3_set_scl(void *data, rt_int32_t state) +{ + struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data; + if (state) + { + gpio_set_level(cfg->scl, PIN_HIGH); + } + else + { + gpio_set_level(cfg->scl, PIN_LOW); + } +} + +/** + * @brief This function gets the sda pin state. + * @param data + * @retval None + */ +static rt_int32_t esp32c3_get_sda(void *data) +{ + struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data; + return gpio_get_level(cfg->sda); +} + +/** + * @brief This function gets the scl pin state. + * @param data + * @retval None + */ +static rt_int32_t esp32c3_get_scl(void *data) +{ + struct esp32c3_soft_i2c_config* cfg = (struct esp32c3_soft_i2c_config*)data; + return gpio_get_level(cfg->scl); +} + +/** + * @brief The time delay function. + * @param us + * @retval None + */ +static void esp32c3_udelay(rt_uint32_t us) +{ + rt_hw_us_delay(us); +} + +/* + * if i2c is locked, this function will unlock it + * + * @param esp32 config class + * + * @return RT_EOK indicates successful unlock. + */ +/* */ +static rt_err_t esp32c3_i2c_bus_unlock(const struct esp32c3_soft_i2c_config *cfg) +{ + rt_int32_t i = 0; + + if (PIN_LOW == rt_pin_read(cfg->sda)) + { + /* 输出9个时钟 解锁IIC死锁 */ + while (i++ < 9) + { + gpio_set_level(cfg->scl, PIN_HIGH); + esp32c3_udelay(100); + gpio_set_level(cfg->scl, PIN_LOW); + esp32c3_udelay(100); + } + } + if (PIN_LOW == gpio_get_level(cfg->sda)) + { + return -RT_ERROR; + } + return RT_EOK; +} + +static const struct rt_i2c_bit_ops esp32c3_bit_ops_default = +{ + .data = RT_NULL, + .set_sda = esp32c3_set_sda, + .set_scl = esp32c3_set_scl, + .get_sda = esp32c3_get_sda, + .get_scl = esp32c3_get_scl, + .udelay = esp32c3_udelay, + .delay_us = 1, + .timeout = 100 +}; + +int rt_sw_i2c_init(void) +{ + /* I2C设备数量 */ + rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct esp32c3_i2c); + rt_err_t result; + /* 循环初始化 */ + for (int i = 0; i < obj_num; i++) + { + /* 注册方法 */ + i2c_obj[i].ops = esp32c3_bit_ops_default; + /* 设备硬件数据 */ + i2c_obj[i].ops.data = (void*)&soft_i2c_config[i]; + /* 保存设备方法 */ + i2c_obj[i].i2c_bus.priv = &i2c_obj[i].ops; + + esp32c3_i2c_gpio_init(&i2c_obj[i]); + result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c_bus, soft_i2c_config[i].bus_name); + RT_ASSERT(result == RT_EOK); + + esp32c3_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_APP_EXPORT(rt_sw_i2c_init); + +#endif /* BSP_USING_SW_I2C */ +#endif /* RT_USING_I2C */ \ No newline at end of file diff --git a/bsp/ESP32_C3/drivers/drv_sw_i2c.h b/bsp/ESP32_C3/drivers/drv_sw_i2c.h new file mode 100644 index 0000000000..ab353e473f --- /dev/null +++ b/bsp/ESP32_C3/drivers/drv_sw_i2c.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2024 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-12-07 wumingzi first version + */ +#ifndef __DRV_HW_I2C_H__ +#define __DRV_HW_I2C_H__ + +#include +#include +#include "sdkconfig.h" + +/* esp32c3 config class */ +struct esp32c3_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; + +/* esp32c3 i2c dirver class */ +struct esp32c3_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device i2c_bus; +}; + +int rt_hw_i2c_init(void); + +#endif /* __DRV_HW_I2C_H__ */ \ No newline at end of file