diff --git a/bsp/lpc55sxx/Libraries/drivers/SConscript b/bsp/lpc55sxx/Libraries/drivers/SConscript index ab3ab0540ee6969350fc21c948df684996f33747..b864761e98ca53b9d8546b10edc1bf0b4738c80c 100644 --- a/bsp/lpc55sxx/Libraries/drivers/SConscript +++ b/bsp/lpc55sxx/Libraries/drivers/SConscript @@ -49,6 +49,9 @@ if GetDepend('BSP_USING_I2S'): if GetDepend('BSP_USING_WM8904'): src += ['drv_sound_wm8904.c'] +if GetDepend('BSP_USING_SOFT_I2C'): + src += ['drv_soft_i2c.c'] + path = [cwd,cwd + '/config'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/lpc55sxx/Libraries/drivers/drv_soft_i2c.c b/bsp/lpc55sxx/Libraries/drivers/drv_soft_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..2feeeb2269cd066e2597ba1d8aa1002f29a5b615 --- /dev/null +++ b/bsp/lpc55sxx/Libraries/drivers/drv_soft_i2c.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-04-11 linshire the first version + */ + +#include +#include "drv_soft_i2c.h" + +#ifdef RT_USING_I2C + +#define LOG_TAG "drv.i2c" +#include + +#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) && !defined(BSP_USING_I2C4) +#error "Please define at least one BSP_USING_I2Cx" +/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +static const struct lpc55s69_soft_i2c_config soft_i2c_config[] = +{ +#ifdef BSP_USING_SOFT_I2C1 + SOFT_I2C1_BUS_CONFIG, +#endif +#ifdef BSP_USING_SOFT_I2C2 + SOFT_I2C2_BUS_CONFIG, +#endif +}; + +static struct lpc55s69_i2c i2c_obj[sizeof(soft_i2c_config) / sizeof(soft_i2c_config[0])]; + +/** + * This function initializes the i2c pin. + * + * @param lpc55s69 i2c dirver class. + */ +static void lpc55s69_i2c_gpio_init(struct lpc55s69_i2c *i2c) +{ + struct lpc55s69_soft_i2c_config* cfg = (struct lpc55s69_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 lpc55s69 config class. + * @param The sda pin state. + */ +static void lpc55s69_set_sda(void *data, rt_int32_t state) +{ + struct lpc55s69_soft_i2c_config* cfg = (struct lpc55s69_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 lpc55s69 config class. + * @param The scl pin state. + */ +static void lpc55s69_set_scl(void *data, rt_int32_t state) +{ + struct lpc55s69_soft_i2c_config* cfg = (struct lpc55s69_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 lpc55s69_get_sda(void *data) +{ + struct lpc55s69_soft_i2c_config* cfg = (struct lpc55s69_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 lpc55s69_get_scl(void *data) +{ + struct lpc55s69_soft_i2c_config* cfg = (struct lpc55s69_soft_i2c_config*)data; + return rt_pin_read(cfg->scl); +} +/** + * The time delay function. + * + * @param microseconds. + */ +static void lpc55s69_udelay(rt_uint32_t us) +{ + rt_uint32_t ticks; + rt_uint32_t told, tnow, tcnt = 0; + rt_uint32_t reload = SysTick->LOAD; + + ticks = us * reload / (1000000 / RT_TICK_PER_SECOND); + told = SysTick->VAL; + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + break; + } + } + } +} + +static const struct rt_i2c_bit_ops lpc55s69_bit_ops_default = +{ + .data = RT_NULL, + .set_sda = lpc55s69_set_sda, + .set_scl = lpc55s69_set_scl, + .get_sda = lpc55s69_get_sda, + .get_scl = lpc55s69_get_scl, + .udelay = lpc55s69_udelay, + .delay_us = 1, + .timeout = 100 +}; + +/** + * if i2c is locked, this function will unlock it + * + * @param lpc55s69 config class + * + * @return RT_EOK indicates successful unlock. + */ +static rt_err_t lpc55s69_i2c_bus_unlock(const struct lpc55s69_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); + lpc55s69_udelay(100); + rt_pin_write(cfg->scl, PIN_LOW); + lpc55s69_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 lpc55s69_i2c); i++) + { + i2c_obj[i].ops = lpc55s69_bit_ops_default; + i2c_obj[i].ops.data = (void*)&soft_i2c_config[i]; + i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops; + lpc55s69_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); + lpc55s69_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/lpc55sxx/Libraries/drivers/drv_soft_i2c.h b/bsp/lpc55sxx/Libraries/drivers/drv_soft_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..ba15c2129d9325e85469f955ce4ac0370fcf2120 --- /dev/null +++ b/bsp/lpc55sxx/Libraries/drivers/drv_soft_i2c.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-04-11 linshrie first version + */ + +#ifndef __DRV_I2C__ +#define __DRV_I2C__ + +#include +#include +#include + +/* lpc55s69 config class */ +struct lpc55s69_soft_i2c_config +{ + rt_uint8_t scl; + rt_uint8_t sda; + const char *bus_name; +}; +/* lpc55s69 i2c dirver class */ +struct lpc55s69_i2c +{ + struct rt_i2c_bit_ops ops; + struct rt_i2c_bus_device i2c2_bus; +}; + +#ifdef BSP_USING_SOFT_I2C1 +#define SOFT_I2C1_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C1_SCL_PIN, \ + .sda = BSP_SOFT_I2C1_SCL_PIN, \ + .bus_name = "i2c1", \ + } +#endif + +#ifdef BSP_USING_SOFT_I2C2 +#define SOFT_I2C2_BUS_CONFIG \ + { \ + .scl = BSP_SOFT_I2C2_SCL_PIN, \ + .sda = BSP_SOFT_I2C2_SCL_PIN, \ + .bus_name = "i2c2", \ + } +#endif /*BSP_USING_I2C2*/ + +int rt_hw_i2c_init(void); + +#endif diff --git a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig index ea54edc664b42d5827271b2224b1e69e33934504..4289e5eb3389df59d59322595affdad5ffe0a02e 100644 --- a/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig +++ b/bsp/lpc55sxx/lpc55s69_nxp_evk/board/Kconfig @@ -116,6 +116,48 @@ menu "On-chip Peripheral Drivers" endchoice endif endif + + menuconfig BSP_USING_SOFT_I2C + bool "Enable I2C Bus" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + default n + + if BSP_USING_SOFT_I2C + config BSP_USING_SOFT_I2C1 + bool "Enable I2C1 Bus (software simulation)" + default n + + if BSP_USING_SOFT_I2C1 + comment "Notice: PB10 --> 26; PB11 --> 27" + + config BSP_SOFT_I2C1_SCL_PIN + int "i2c1 SCL pin number" + range 0 79 + default 26 + config BSP_SOFT_I2C1_SDA_PIN + int "i2c1 SDA pin number" + range 0 79 + default 27 + endif + + config BSP_USING_SOFT_I2C2 + bool "Enable I2C2 Bus (software simulation)" + default n + + if BSP_USING_SOFT_I2C2 + comment "Notice: PC1 --> 33; PC0 --> 32" + config BSP_SOFT_I2C2_SCL_PIN + int "i2c2 SCL pin number" + range 0 79 + default 32 + config BSP_SOFT_I2C2_SDA_PIN + int "i2c2 SDA pin number" + range 0 79 + default 33 + endif + endif menuconfig BSP_USING_SPI config BSP_USING_SPI diff --git a/bsp/lpc55sxx/tools/sdk_dist.py b/bsp/lpc55sxx/tools/sdk_dist.py index 6fbddfbd4ee4ceabb911960e202295c5a4e8e081..4a474023c20667a87fedb40ce38f9b5edd78e698 100644 --- a/bsp/lpc55sxx/tools/sdk_dist.py +++ b/bsp/lpc55sxx/tools/sdk_dist.py @@ -18,3 +18,20 @@ def dist_do_building(BSP_ROOT, dist_dir): print("=> copy bsp library") bsp_copy_files(os.path.join(library_path, rtconfig.BSP_LIBRARY_TYPE), os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + # change RTT_ROOT in Kconfig + if not os.path.isfile(os.path.join(dist_dir, 'Kconfig')): + return + + with open(os.path.join(dist_dir, 'Kconfig'), 'r') as f: + data = f.readlines() + with open(os.path.join(dist_dir, 'Kconfig'), 'w') as f: + found = 0 + for line in data: + if line.find('RTT_ROOT') != -1: + found = 1 + if line.find('../Libraries') != -1 and found: + position = line.find('../Libraries') + line = line[0:position] + 'Libraries/Kconfig"\n' + found = 0 + f.write(line)