summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorsp-cai <[email protected]>2023-10-17 23:24:32 +0800
committerGitHub <[email protected]>2023-10-17 11:24:32 -0400
commit7f6f086601a5e3f964dc6d3bf958d1eb250b7d0e (patch)
tree41242510b540085149a1e048c26292d0b4b19e5a /components
parent33fe6b320d645d48b912dd73981f9668dbec49b2 (diff)
[components][i2c]增加通用的软件模拟 I2C (#7850)
Diffstat (limited to 'components')
-rwxr-xr-xcomponents/drivers/Kconfig200
-rw-r--r--components/drivers/i2c/SConscript2
-rw-r--r--components/drivers/i2c/soft_i2c.c263
3 files changed, 465 insertions, 0 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index 4fd3553df2..1bb9a07c91 100755
--- a/components/drivers/Kconfig
+++ b/components/drivers/Kconfig
@@ -130,6 +130,206 @@ if RT_USING_I2C
bool "Use simulate I2C debug message"
default n
endif
+
+ config RT_USING_SOFT_I2C
+ bool "Use GPIO to soft simulate I2C"
+ default n
+ select RT_USING_PIN
+ select RT_USING_I2C_BITOPS
+ if RT_USING_SOFT_I2C
+ config RT_USING_SOFT_I2C1
+ bool "Enable I2C1 Bus (software simulation)"
+ default y
+ if RT_USING_SOFT_I2C1
+ config RT_SOFT_I2C1_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 1
+ config RT_SOFT_I2C1_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 2
+ config RT_SOFT_I2C1_BUS_NAME
+ string "Bus name"
+ default i2c1
+ config RT_SOFT_I2C1_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C1_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C2
+ bool "Enable I2C2 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C2
+ config RT_SOFT_I2C2_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 3
+ config RT_SOFT_I2C2_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 4
+ config RT_SOFT_I2C2_BUS_NAME
+ string "Bus name"
+ default i2c2
+ config RT_SOFT_I2C2_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C2_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C3
+ bool "Enable I2C3 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C3
+ config RT_SOFT_I2C3_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 5
+ config RT_SOFT_I2C3_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 6
+ config RT_SOFT_I2C3_BUS_NAME
+ string "Bus name"
+ default i2c3
+ config RT_SOFT_I2C3_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C3_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C4
+ bool "Enable I2C4 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C4
+ config RT_SOFT_I2C4_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 7
+ config RT_SOFT_I2C4_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 8
+ config RT_SOFT_I2C4_BUS_NAME
+ string "Bus name"
+ default i2c4
+ config RT_SOFT_I2C4_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C4_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C5
+ bool "Enable I2C5 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C5
+ config RT_SOFT_I2C5_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 9
+ config RT_SOFT_I2C5_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C5_BUS_NAME
+ string "Bus name"
+ default i2c5
+ config RT_SOFT_I2C5_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C5_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C6
+ bool "Enable I2C6 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C6
+ config RT_SOFT_I2C6_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 11
+ config RT_SOFT_I2C6_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 12
+ config RT_SOFT_I2C6_BUS_NAME
+ string "Bus name"
+ default i2c6
+ config RT_SOFT_I2C6_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C6_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C7
+ bool "Enable I2C7 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C7
+ config RT_SOFT_I2C7_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 13
+ config RT_SOFT_I2C7_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 14
+ config RT_SOFT_I2C7_BUS_NAME
+ string "Bus name"
+ default i2c7
+ config RT_SOFT_I2C7_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C7_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ config RT_USING_SOFT_I2C8
+ bool "Enable I2C8 Bus (software simulation)"
+ default n
+ if RT_USING_SOFT_I2C8
+ config RT_SOFT_I2C8_SCL_PIN
+ int "SCL pin number"
+ range 0 32767
+ default 15
+ config RT_SOFT_I2C8_SDA_PIN
+ int "SDA pin number"
+ range 0 32767
+ default 16
+ config RT_SOFT_I2C8_BUS_NAME
+ string "Bus name"
+ default i2c8
+ config RT_SOFT_I2C8_TIMING_DELAY
+ int "Timing delay (us)"
+ range 0 32767
+ default 10
+ config RT_SOFT_I2C8_TIMING_TIMEOUT
+ int "Timing timeout (tick)"
+ range 0 32767
+ default 10
+ endif
+ endif
endif
config RT_USING_PHY
diff --git a/components/drivers/i2c/SConscript b/components/drivers/i2c/SConscript
index 5e85a645a7..aef9f5be9b 100644
--- a/components/drivers/i2c/SConscript
+++ b/components/drivers/i2c/SConscript
@@ -9,6 +9,8 @@ i2c_dev.c
if GetDepend('RT_USING_I2C_BITOPS'):
src = src + ['i2c-bit-ops.c']
+if GetDepend('RT_USING_SOFT_I2C'):
+ src = src + ['soft_i2c.c']
# The set of source files associated with this SConscript file.
path = [cwd + '/../include']
diff --git a/components/drivers/i2c/soft_i2c.c b/components/drivers/i2c/soft_i2c.c
new file mode 100644
index 0000000000..7c3bd1e93a
--- /dev/null
+++ b/components/drivers/i2c/soft_i2c.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2023-07-30 sp-cai first version
+ */
+
+#include <rtdevice.h>
+
+#ifdef RT_USING_SOFT_I2C
+#if !defined(RT_USING_SOFT_I2C1) && !defined(RT_USING_SOFT_I2C2) &&\
+ !defined(RT_USING_SOFT_I2C3) && !defined(RT_USING_SOFT_I2C4) &&\
+ !defined(RT_USING_SOFT_I2C5) && !defined(RT_USING_SOFT_I2C6) &&\
+ !defined(RT_USING_SOFT_I2C7) && !defined(RT_USING_SOFT_I2C8)
+ #error "Please define at least one RT_USING_SOFT_I2Cx"
+ /*
+ This driver can be disabled at:
+ menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers
+ */
+#endif
+
+#define DBG_ENABLE
+#define DBG_TAG "I2C_S"
+#ifdef RT_I2C_BITOPS_DEBUG
+ #define DBG_LEVEL DBG_LOG
+#endif
+#include <rtdbg.h>
+
+/* i2c config class */
+struct soft_i2c_config
+{
+ rt_base_t scl_pin;
+ rt_base_t sda_pin;
+ const char *bus_name;
+ rt_uint16_t timing_delay; /* scl and sda line delay */
+ rt_uint16_t timing_timeout; /* in tick */
+};
+
+/* i2c dirver class */
+struct rt_soft_i2c
+{
+ struct rt_i2c_bus_device i2c_bus;
+ struct rt_i2c_bit_ops ops;
+};
+
+struct soft_i2c_config i2c_cfg[] =
+{
+ #ifdef RT_USING_SOFT_I2C1
+ {
+ .scl_pin = RT_SOFT_I2C1_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C1_SDA_PIN,
+ .bus_name = RT_SOFT_I2C1_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C1_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C1_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C1
+ #ifdef RT_USING_SOFT_I2C2
+ {
+ .scl_pin = RT_SOFT_I2C2_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C2_SDA_PIN,
+ .bus_name = RT_SOFT_I2C2_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C2_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C2_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C2
+ #ifdef RT_USING_SOFT_I2C3
+ {
+ .scl_pin = RT_SOFT_I2C3_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C3_SDA_PIN,
+ .bus_name = RT_SOFT_I2C3_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C3_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C3_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C3
+ #ifdef RT_USING_SOFT_I2C4
+ {
+ .scl_pin = RT_SOFT_I2C4_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C4_SDA_PIN,
+ .bus_name = RT_SOFT_I2C4_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C4_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C4_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C4
+ #ifdef RT_USING_SOFT_I2C5
+ {
+ .scl_pin = RT_SOFT_I2C5_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C5_SDA_PIN,
+ .bus_name = RT_SOFT_I2C5_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C5_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C5_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C5
+ #ifdef RT_USING_SOFT_I2C6
+ {
+ .scl_pin = RT_SOFT_I2C6_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C6_SDA_PIN,
+ .bus_name = RT_SOFT_I2C6_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C6_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C6_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C6
+ #ifdef RT_USING_SOFT_I2C7
+ {
+ .scl_pin = RT_SOFT_I2C7_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C7_SDA_PIN,
+ .bus_name = RT_SOFT_I2C7_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C7_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C7_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C7
+ #ifdef RT_USING_SOFT_I2C8
+ {
+ .scl_pin = RT_SOFT_I2C8_SCL_PIN,
+ .sda_pin = RT_SOFT_I2C8_SDA_PIN,
+ .bus_name = RT_SOFT_I2C8_BUS_NAME,
+ .timing_delay = RT_SOFT_I2C8_TIMING_DELAY,
+ .timing_timeout = RT_SOFT_I2C8_TIMING_TIMEOUT,
+ },
+ #endif //RT_USING_SOFT_I2C8
+};
+
+
+static struct rt_soft_i2c i2c_bus_obj[sizeof(i2c_cfg) / sizeof(i2c_cfg[0])] =
+{ 0 };
+
+/**
+* This function initializes the i2c pin.
+* @param i2c config class.
+*/
+static void pin_init(const struct soft_i2c_config *cfg)
+{
+ rt_pin_mode(cfg->scl_pin, PIN_MODE_OUTPUT_OD);
+ rt_pin_mode(cfg->sda_pin, PIN_MODE_OUTPUT_OD);
+ rt_pin_write(cfg->scl_pin, PIN_HIGH);
+ rt_pin_write(cfg->sda_pin, PIN_HIGH);
+}
+
+
+/**
+* This function sets the sda pin.
+* @param i2c config class.
+* @param The sda pin state.
+*/
+static void set_sda(void *cfg, rt_int32_t value)
+{
+ rt_pin_write(((const struct soft_i2c_config*)cfg)->sda_pin, value);
+}
+
+/**
+* This function sets the scl pin.
+* @param i2c config class.
+* @param The sda pin state.
+*/
+static void set_scl(void *cfg, rt_int32_t value)
+{
+ rt_pin_write(((const struct soft_i2c_config*)cfg)->scl_pin, value);
+}
+
+/**
+* This function gets the sda pin state.
+* @param i2c config class.
+*/
+static rt_int32_t get_sda(void *cfg)
+{
+ return rt_pin_read(((const struct soft_i2c_config*)cfg)->sda_pin);
+}
+
+/**
+* This function gets the scl pin state.
+* @param i2c config class.
+*/
+static rt_int32_t get_scl(void *cfg)
+{
+ return rt_pin_read(((const struct soft_i2c_config*)cfg)->scl_pin);
+}
+
+
+static const struct rt_i2c_bit_ops soft_i2c_ops =
+{
+ .set_sda = set_sda,
+ .set_scl = set_scl,
+ .get_sda = get_sda,
+ .get_scl = get_scl,
+ .udelay = rt_hw_us_delay,
+};
+
+/**
+* if i2c is locked, this function will unlock it
+*
+* @param i2c config class.
+*
+* @return RT_EOK indicates successful unlock.
+*/
+static rt_err_t i2c_bus_unlock(const struct soft_i2c_config *cfg)
+{
+ rt_ubase_t i = 0;
+
+ if(PIN_LOW == rt_pin_read(cfg->sda_pin))
+ {
+ while(i++ < 9)
+ {
+ rt_pin_write(cfg->scl_pin, PIN_HIGH);
+ rt_hw_us_delay(cfg->timing_delay);
+ rt_pin_write(cfg->scl_pin, PIN_LOW);
+ rt_hw_us_delay(cfg->timing_delay);
+ }
+ }
+ if(PIN_LOW == rt_pin_read(cfg->sda_pin))
+ {
+ return -RT_ERROR;
+ }
+
+ return RT_EOK;
+}
+
+/* I2C initialization function */
+int rt_soft_i2c_init(void)
+{
+ int err = RT_EOK;
+ struct rt_soft_i2c *obj;
+
+ for(int i = 0; i < sizeof(i2c_bus_obj) / sizeof(i2c_bus_obj[0]); i++)
+ {
+ struct soft_i2c_config *cfg = &i2c_cfg[i];
+
+ pin_init(cfg);
+
+ obj = &i2c_bus_obj[i];
+ obj->ops = soft_i2c_ops;
+ obj->ops.data = cfg;
+ obj->i2c_bus.priv = &obj->ops;
+ obj->ops.delay_us = cfg->timing_delay;
+ obj->ops.timeout = cfg->timing_timeout;
+ if(rt_i2c_bit_add_bus(&obj->i2c_bus, cfg->bus_name) == RT_EOK)
+ {
+ i2c_bus_unlock(cfg);
+ LOG_D("Software simulation %s init done"
+ ", SCL pin: 0x%02X, SDA pin: 0x%02X"
+ , cfg->bus_name
+ , cfg->scl_pin
+ , cfg->sda_pin
+ );
+ }
+ else
+ {
+ err++;
+ LOG_E("Software simulation %s init fail"
+ ", SCL pin: 0x%02X, SDA pin: 0x%02X"
+ , cfg->bus_name
+ , cfg->scl_pin
+ , cfg->sda_pin
+ );
+ }
+ }
+
+ return err;
+}
+INIT_PREV_EXPORT(rt_soft_i2c_init);
+
+#endif // RT_USING_SOFT_I2C