From f588bf49b614df5ef164b828b87fcfedb1641b09 Mon Sep 17 00:00:00 2001 From: wirano Date: Thu, 11 Apr 2024 16:59:10 +0800 Subject: [PATCH] bsp/tm4c123: add hardware i2c support --- bsp/tm4c123bsp/board/Kconfig | 80 ++++++- bsp/tm4c123bsp/board/board.c | 3 + bsp/tm4c123bsp/board/board.h | 4 + bsp/tm4c123bsp/libraries/Drivers/SConscript | 6 +- .../libraries/Drivers/config/i2c_config.h | 93 +++++++ bsp/tm4c123bsp/libraries/Drivers/drv_i2c.c | 226 ++++++++++++++++++ bsp/tm4c123bsp/libraries/Drivers/drv_i2c.h | 31 +++ .../libraries/TivaWare_C_series/SConscript | 3 +- 8 files changed, 429 insertions(+), 17 deletions(-) create mode 100644 bsp/tm4c123bsp/libraries/Drivers/config/i2c_config.h create mode 100644 bsp/tm4c123bsp/libraries/Drivers/drv_i2c.c create mode 100644 bsp/tm4c123bsp/libraries/Drivers/drv_i2c.h diff --git a/bsp/tm4c123bsp/board/Kconfig b/bsp/tm4c123bsp/board/Kconfig index 9c93c1a0cc..b7356b7fad 100644 --- a/bsp/tm4c123bsp/board/Kconfig +++ b/bsp/tm4c123bsp/board/Kconfig @@ -188,21 +188,75 @@ menu "On-chip Peripheral Drivers" default n endif - menuconfig BSP_USING_I2C1 - bool "Enable I2C1 BUS (software simulation)" + menuconfig BSP_USING_I2C + bool "Enable I2C BUS" default n select RT_USING_I2C - select RT_USING_I2C_BITOPS - select RT_USING_PIN - if BSP_USING_I2C1 - config BSP_I2C1_SCL_PIN - int "i2c1 scl pin number" - range 0 175 - default 22 - config BSP_I2C1_SDA_PIN - int "I2C1 sda pin number" - range 0 175 - default 23 + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0 BUS" + default n + if BSP_USING_I2C0 + choice + prompt "I2C0 CLK frequency" + default BSP_I2C0_CLK_100 + + config BSP_I2C0_CLK_100 + bool "100kHz" + + config BSP_I2C0_CLK_400 + bool "400kHz" + endchoice + endif + + config BSP_USING_I2C1 + bool "Enable I2C1 BUS" + default n + if BSP_USING_I2C1 + choice + prompt "I2C1 CLK frequency" + default BSP_I2C1_CLK_100 + + config BSP_I2C1_CLK_100 + bool "100kHz" + + config BSP_I2C1_CLK_400 + bool "400kHz" + endchoice + endif + + config BSP_USING_I2C2 + bool "Enable I2C2 BUS" + default n + if BSP_USING_I2C2 + choice + prompt "I2C2 CLK frequency" + default BSP_I2C3_CLK_100 + + config BSP_I2C2_CLK_100 + bool "100kHz" + + config BSP_I2C2_CLK_400 + bool "400kHz" + endchoice + endif + + config BSP_USING_I2C3 + bool "Enable I2C3 BUS" + default n + if BSP_USING_I2C3 + choice + prompt "I2C3 CLK frequency" + default BSP_I2C4_CLK_100 + + config BSP_I2C3_CLK_100 + bool "100kHz" + + config BSP_I2C3_CLK_400 + bool "400kHz" + endchoice + endif + endif menuconfig BSP_USING_TIM diff --git a/bsp/tm4c123bsp/board/board.c b/bsp/tm4c123bsp/board/board.c index 4f75212b08..0748f2436b 100644 --- a/bsp/tm4c123bsp/board/board.c +++ b/bsp/tm4c123bsp/board/board.c @@ -58,6 +58,9 @@ void rt_hw_board_init() #endif #ifdef RT_USING_PWM rt_hw_pwm_init(); +#endif +#ifdef RT_USING_I2C + rt_hw_i2c_init(); #endif /* Call components board initial (use INIT_BOARD_EXPORT()) */ #ifdef RT_USING_COMPONENTS_INIT diff --git a/bsp/tm4c123bsp/board/board.h b/bsp/tm4c123bsp/board/board.h index 0f8c5aff40..990da9b42a 100644 --- a/bsp/tm4c123bsp/board/board.h +++ b/bsp/tm4c123bsp/board/board.h @@ -47,6 +47,10 @@ #include "drv_spi.h" #endif /* RT_USING_SPI*/ +#ifdef RT_USING_I2C +#include "drv_i2c.h" +#endif /* RT_USING_I2C*/ + #endif /*__BOARD_H__*/ /************************** end of file ******************/ diff --git a/bsp/tm4c123bsp/libraries/Drivers/SConscript b/bsp/tm4c123bsp/libraries/Drivers/SConscript index d50fd5cadc..94e0d77ba1 100644 --- a/bsp/tm4c123bsp/libraries/Drivers/SConscript +++ b/bsp/tm4c123bsp/libraries/Drivers/SConscript @@ -26,9 +26,9 @@ if GetDepend(['RT_USING_SPI']): if GetDepend(['RT_USING_QSPI']): src += ['drv_qspi.c'] -if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']): - if GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3') or GetDepend('BSP_USING_I2C4'): - src += ['drv_soft_i2c.c'] +if GetDepend(['RT_USING_I2C']): + if GetDepend('BSP_USING_I2C0') or GetDepend('BSP_USING_I2C1') or GetDepend('BSP_USING_I2C2') or GetDepend('BSP_USING_I2C3'): + src += ['drv_i2c.c'] if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']): src += ['drv_eth.c'] diff --git a/bsp/tm4c123bsp/libraries/Drivers/config/i2c_config.h b/bsp/tm4c123bsp/libraries/Drivers/config/i2c_config.h new file mode 100644 index 0000000000..f89a3c3d8b --- /dev/null +++ b/bsp/tm4c123bsp/libraries/Drivers/config/i2c_config.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-20 wirano first version + */ + +#ifndef __I2C_CONFIG_H__ +#define __I2C_CONFIG_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BSP_I2C0_CLK_100) +#define I2C0_CLK 100000 +#elif defined(BSP_I2C0_CLK_400) +#define I2C0_CLK 400000 +#endif + +#if defined(BSP_I2C1_CLK_100) +#define I2C1_CLK 100000 +#elif defined(BSP_I2C1_CLK_400) +#define I2C1_CLK 400000 +#endif + +#if defined(BSP_I2C2_CLK_100) +#define I2C2_CLK 100000 +#elif defined(BSP_I2C2_CLK_400) +#define I2C2_CLK 400000 +#endif + +#if defined(BSP_I2C3_CLK_100) +#define I2C3_CLK 100000 +#elif defined(BSP_I2C3_CLK_400) +#define I2C3_CLK 400000 +#endif + +#ifdef BSP_USING_I2C0 +#ifndef I2C0_BUS_CONFIG +#define I2C0_BUS_CONFIG \ + { \ + .base = I2C0_BASE, \ + .bus_name = "i2c0", \ + .clk_freq = I2C0_CLK, \ + } +#endif /* I2C0_BUS_CONFIG */ +#endif /* BSP_USING_I2C0 */ + +#ifdef BSP_USING_I2C1 +#ifndef I2C1_BUS_CONFIG +#define I2C1_BUS_CONFIG \ + { \ + .base = I2C1_BASE, \ + .bus_name = "i2c1", \ + .clk_freq = I2C1_CLK, \ + } +#endif /* I2C1_BUS_CONFIG */ +#endif /* BSP_USING_I2C1 */ + +#ifdef BSP_USING_I2C2 +#ifndef I2C2_BUS_CONFIG +#define I2C2_BUS_CONFIG \ + { \ + .base = I2C2_BASE, \ + .bus_name = "i2c2", \ + .clk_freq = I2C2_CLK, \ + } +#endif /* I2C2_BUS_CONFIG */ +#endif /* BSP_USING_I2C2 */ + +#ifdef BSP_USING_I2C3 +#ifndef I2C3_BUS_CONFIG +#define I2C3_BUS_CONFIG \ + { \ + .base = I2C3_BASE, \ + .bus_name = "i2c3", \ + .clk_freq = I2C3_CLK, \ + } +#endif /* I2C3_BUS_CONFIG */ +#endif /* BSP_USING_I2C3 */ + +#ifdef __cplusplus +} +#endif + +#endif //__I2C_CONFIG_H__ diff --git a/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.c b/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.c new file mode 100644 index 0000000000..066e16fa22 --- /dev/null +++ b/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-20 wirano first version + */ + + +#include +#include +#include + +#ifdef BSP_USING_I2C + +#if defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3) + +#include "drv_i2c.h" +#include "inc/hw_memmap.h" +#include +#include "i2c_config.h" +#include "driverlib/rom.h" +#include "driverlib/sysctl.h" +#include "driverlib/pin_map.h" +#include "driverlib/gpio.h" +#include "driverlib/i2c.h" + +enum { +#ifdef BSP_USING_I2C0 + I2C0_INDEX, +#endif +#ifdef BSP_USING_I2C1 + I2C1_INDEX, +#endif +#ifdef BSP_USING_I2C2 + I2C2_INDEX, +#endif +#ifdef BSP_USING_I2C3 + I2C3_INDEX, +#endif +}; + +static struct tm4c123_i2c tm4c123_i2cs[] = + { +#ifdef BSP_USING_I2C0 + I2C0_BUS_CONFIG, +#endif + +#ifdef BSP_USING_I2C1 + I2C1_BUS_CONFIG, +#endif + +#ifdef BSP_USING_I2C2 + I2C2_BUS_CONFIG, +#endif + +#ifdef BSP_USING_I2C3 + I2C3_BUS_CONFIG, +#endif + }; + + +static rt_ssize_t tm4c123_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); + + +struct rt_i2c_bus_device_ops tm4c123_i2c_ops = + { + tm4c123_i2c_xfer, + RT_NULL, + RT_NULL + }; + + +static rt_ssize_t tm4c123_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) { + RT_ASSERT(bus != RT_NULL); + RT_ASSERT(msgs != RT_NULL); + + struct rt_i2c_msg *msg; + struct tm4c123_i2c *i2c_info = (struct tm4c123_i2c *) bus; + + rt_err_t ret = -RT_ERROR; + rt_uint32_t i; + + for (i = 0; i < num; i++) { + msg = &msgs[i]; + + if (msg->flags & RT_I2C_ADDR_10BIT) { + LOG_E("does not support 10bits address!\n"); + } + + if (msg->flags & RT_I2C_RD) { + rt_uint8_t *data = msg->buf; + + ROM_I2CMasterSlaveAddrSet(i2c_info->base, msg->addr, true); + + if (msg->flags & RT_I2C_NO_START) { + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT); + while (ROM_I2CMasterBusy(i2c_info->base)); + *data = ROM_I2CMasterDataGet(i2c_info->base); + } else { + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_START); + while (ROM_I2CMasterBusy(i2c_info->base)); + *data = ROM_I2CMasterDataGet(i2c_info->base); + } + + if (msg->len > 1) { + data++; + + for (int j = 1; j < msg->len - 1; ++j) { + + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT); + while (ROM_I2CMasterBusy(i2c_info->base)); + *data = ROM_I2CMasterDataGet(i2c_info->base); + data++; + } + + if (msg->flags & RT_I2C_NO_STOP) { + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_CONT); + while (ROM_I2CMasterBusy(i2c_info->base)); + *data = ROM_I2CMasterDataGet(i2c_info->base); + } else { + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + while (ROM_I2CMasterBusy(i2c_info->base)); + *data = ROM_I2CMasterDataGet(i2c_info->base); + } + } + } else { + rt_uint8_t *data = msg->buf; + + ROM_I2CMasterSlaveAddrSet(i2c_info->base, msg->addr, false); + + // use single send when data len = 1 + if (msg->len == 1) { + if (msg->flags & RT_I2C_NO_START) { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT); + } else if (msg->flags & RT_I2C_NO_STOP) { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT); + } else { + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_SINGLE_SEND); + ROM_I2CMasterDataPut(i2c_info->base, *data); + } + while (ROM_I2CMasterBusy(i2c_info->base)); + // otherwise use burst send + } else { + if (msg->flags & RT_I2C_NO_START) { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT); + while (ROM_I2CMasterBusy(i2c_info->base)); + } else { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_START); + while (ROM_I2CMasterBusy(i2c_info->base)); + } + + data++; + + for (int j = 1; j < msg->len - 1; ++j) { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT); + while (ROM_I2CMasterBusy(i2c_info->base)); + data++; + } + + if (msg->flags & RT_I2C_NO_STOP) { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_CONT); + } else { + ROM_I2CMasterDataPut(i2c_info->base, *data); + ROM_I2CMasterControl(i2c_info->base, I2C_MASTER_CMD_BURST_SEND_FINISH); + } + while (ROM_I2CMasterBusy(i2c_info->base)); + } + + } + } + ret = i; + return ret; +} + +int rt_hw_i2c_init(void) { + rt_err_t ret = RT_EOK; + + for (uint32_t i = 0; i < sizeof(tm4c123_i2cs) / sizeof(tm4c123_i2cs[0]); i++) { + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); + + ROM_GPIOPinConfigure(GPIO_PB2_I2C0SCL); + ROM_GPIOPinConfigure(GPIO_PB3_I2C0SDA); + + ROM_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); + ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3); + + ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0); + ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0); + while (!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0)); + + // timeout:5ms + ROM_I2CMasterTimeoutSet(I2C0_BASE, 0x7d); + + if (tm4c123_i2cs[i].clk_freq == 400000) { + ROM_I2CMasterInitExpClk(tm4c123_i2cs[i].base, ROM_SysCtlClockGet(), RT_TRUE); + } else { + ROM_I2CMasterInitExpClk(tm4c123_i2cs[i].base, ROM_SysCtlClockGet(), RT_FALSE); + } + ROM_I2CMasterEnable(tm4c123_i2cs[i].base); + + tm4c123_i2cs[i].bus.ops = &tm4c123_i2c_ops; + ret = rt_i2c_bus_device_register(&tm4c123_i2cs[i].bus, tm4c123_i2cs[i].bus_name); + if (ret != RT_EOK) { + LOG_E("rt i2c device %s register failed, status=%d\n", tm4c123_i2cs[i].bus_name, ret); + } + } + + return ret; +} + +INIT_DEVICE_EXPORT(rt_hw_i2c_init); + +#endif /* BSP_USING_I2C1 || BSP_USING_I2C2 || BSP_USING_I2C3 || BSP_USING_I2C4 */ + +#endif /* BSP_USING_I2C */ + diff --git a/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.h b/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.h new file mode 100644 index 0000000000..3f1883e73c --- /dev/null +++ b/bsp/tm4c123bsp/libraries/Drivers/drv_i2c.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-01-20 wirano first version + */ + +#ifndef __DRV_I2C_H__ +#define __DRV_I2C_H__ + + +#include +#include +#include + + +struct tm4c123_i2c +{ + struct rt_i2c_bus_device bus; + uint32_t base; + char *bus_name; + uint32_t clk_freq; +}; + +int rt_hw_i2c_init(void); + +#endif /* __DRV_I2C_H__ */ + diff --git a/bsp/tm4c123bsp/libraries/TivaWare_C_series/SConscript b/bsp/tm4c123bsp/libraries/TivaWare_C_series/SConscript index bd6ba1b1cf..6bd89e4889 100644 --- a/bsp/tm4c123bsp/libraries/TivaWare_C_series/SConscript +++ b/bsp/tm4c123bsp/libraries/TivaWare_C_series/SConscript @@ -20,7 +20,8 @@ tm4c123_driverlib/src/gpio.c if GetDepend(['RT_USING_SERIAL']): src += ['tm4c123_driverlib/src/uart.c'] -#if GetDepend(['RT_USING_I2C']): +if GetDepend(['RT_USING_I2C']): + src += ['tm4c123_driverlib/src/i2c.c'] if GetDepend(['RT_USING_SPI']):