diff --git a/bsp/k210/drivers/drv_i2c.c b/bsp/k210/drivers/drv_i2c.c new file mode 100644 index 0000000000..78d223a3a8 --- /dev/null +++ b/bsp/k210/drivers/drv_i2c.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-21 heyuanjie87 first version + * 2023-03-31 Vandoul formatting code. + */ + +#include +#include + +#include "board.h" +#include "i2c.h" +#include "gpiohs.h" +#include "utils.h" +#include "sleep.h" +#include "fpioa.h" +#ifdef RT_USING_I2C + +#ifndef BSP_I2C0_SCL_PIN +#define BSP_I2C0_SCL_PIN 0 +#endif +#ifndef BSP_I2C0_SDA_PIN +#define BSP_I2C0_SDA_PIN 1 +#endif +#ifndef BSP_I2C1_SCL_PIN +#define BSP_I2C1_SCL_PIN 30 +#endif +#ifndef BSP_I2C1_SDA_PIN +#define BSP_I2C1_SDA_PIN 31 +#endif +#ifndef BSP_I2C2_SCL_PIN +#define BSP_I2C2_SCL_PIN 4 +#endif +#ifndef BSP_I2C2_SDA_PIN +#define BSP_I2C2_SDA_PIN 5 +#endif + +static rt_err_t ki2c_send( + volatile i2c_t *i2c_adapter, + rt_uint8_t *send_buf, + rt_uint32_t send_buf_len) +{ + rt_uint32_t fifo_len, index; + + while (send_buf_len) + { + fifo_len = 8 - i2c_adapter->txflr; + fifo_len = send_buf_len < fifo_len ? send_buf_len : fifo_len; + for (index = 0; index < fifo_len; index++) + i2c_adapter->data_cmd = I2C_DATA_CMD_DATA(*send_buf++); + if (i2c_adapter->tx_abrt_source != 0) + { + while (i2c_adapter->status & I2C_STATUS_ACTIVITY); // + i2c_adapter->clr_intr = i2c_adapter->clr_intr; // + return -RT_ERROR; + } + + send_buf_len -= fifo_len; + } + + return RT_EOK; +} + +static rt_err_t ki2c_recv( + volatile i2c_t *i2c_adapter, + rt_uint8_t *receive_buf, + rt_uint32_t receive_buf_len) +{ + rt_uint32_t fifo_len, index; + rt_uint32_t rx_len = receive_buf_len; + + while (receive_buf_len || rx_len) + { + fifo_len = i2c_adapter->rxflr; + fifo_len = rx_len < fifo_len ? rx_len : fifo_len; + for (index = 0; index < fifo_len; index++) + *receive_buf++ = (rt_uint8_t)i2c_adapter->data_cmd; + rx_len -= fifo_len; + fifo_len = 8 - i2c_adapter->txflr; + fifo_len = receive_buf_len < fifo_len ? receive_buf_len : fifo_len; + for (index = 0; index < fifo_len; index++) + i2c_adapter->data_cmd = I2C_DATA_CMD_CMD; + if (i2c_adapter->tx_abrt_source != 0) + return -RT_ERROR; + receive_buf_len -= fifo_len; + } + + return RT_EOK; +} + +static void ki2c_setaddr( + volatile i2c_t *i2c_adapter, + rt_uint16_t addr, + int width) +{ + i2c_adapter->tar = I2C_TAR_ADDRESS(addr) & I2C_TAR_ADDRESS_MASK; + + if(width == 10) + { + i2c_adapter->tar |= I2C_TAR_10BITADDR_MASTER; + } + else + { + i2c_adapter->tar &= ~I2C_TAR_10BITADDR_MASTER; + } + +} + +static int ki2c_waittx(volatile i2c_t *i2c_adapter, int timeout_ms) +{ + rt_tick_t start; + + start = rt_tick_get(); + while ((i2c_adapter->status & I2C_STATUS_ACTIVITY) || !(i2c_adapter->status & I2C_STATUS_TFE)) + { + if (rt_tick_from_millisecond(rt_tick_get() - start) > timeout_ms) + break; + } + + if (i2c_adapter->tx_abrt_source != 0) + return -RT_ERROR; + + return RT_EOK; +} + +static void ki2c_clearerr(volatile i2c_t *i2c_adapter) +{ + i2c_adapter->clr_tx_abrt = i2c_adapter->clr_tx_abrt; +} + +static rt_ssize_t _i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + rt_ssize_t i; + i2c_t *kbus = (i2c_t *)bus->priv; + rt_err_t status; + int waittx = 0; + + RT_ASSERT(bus != RT_NULL); + if(msgs[0].flags & RT_I2C_ADDR_10BIT) + { + ki2c_setaddr(kbus, msgs[0].addr, 10); + } + else + { + ki2c_setaddr(kbus, msgs[0].addr, 7); + } + + + ki2c_clearerr(kbus); + + for (i = 0; i < num; i++) + { + waittx = 0; + + if (msgs[i].flags & RT_I2C_RD) + { + status = ki2c_recv(kbus, msgs[i].buf, msgs[i].len); + } + else + { + status = ki2c_send(kbus, msgs[i].buf, msgs[i].len); + waittx = 1; + } + + if (status != RT_EOK) + { + goto _out; + } + } + + if (waittx) + { + status = ki2c_waittx(kbus, 2000); + if (status != RT_EOK) + { + goto _out; + } + } + + return i; +_out: + return status; +} + +static const struct rt_i2c_bus_device_ops i2c_ops = +{ + .master_xfer = _i2c_mst_xfer, + .slave_xfer = RT_NULL, + .i2c_bus_control = RT_NULL, +}; + +#ifdef RT_USING_I2C_BITOPS + +typedef struct pin_info_s { + uint32_t scl; + uint32_t sda; +} pin_info_t; + +static void set_sda(void *data, rt_int32_t state) +{ + pin_info_t *pin = (pin_info_t *)data; + /* state = 1: disable output. state = 0: enable output.*/ + set_gpio_bit(gpiohs->output_en.u32, pin->sda, !state); +} + +static void set_scl(void *data, rt_int32_t state) +{ + pin_info_t *pin = (pin_info_t *)data; + /* state = 1: disable output. state = 0: enable output.*/ + set_gpio_bit(gpiohs->output_en.u32, pin->scl, !state); +} + +static rt_int32_t get_sda(void *data) +{ + pin_info_t *pin = (pin_info_t *)data; + /* disable output.*/ + set_gpio_bit(gpiohs->output_en.u32, pin->sda, 0); + + return get_gpio_bit(gpiohs->input_val.u32, pin->sda); +} + +static rt_int32_t get_scl(void *data) +{ + pin_info_t *pin = (pin_info_t *)data; + /* disable output.*/ + set_gpio_bit(gpiohs->output_en.u32, pin->scl, 0); + + return get_gpio_bit(gpiohs->input_val.u32, pin->scl); +} + +static void udelay(rt_uint32_t us) +{ + usleep((uint64_t)us); +} + +static struct rt_i2c_bit_ops bit_ops_0 = +{ + RT_NULL, + set_sda, + set_scl, + get_sda, + get_scl, + udelay, + 5, + 5 +}; + +static struct rt_i2c_bit_ops bit_ops_1 = +{ + RT_NULL, + set_sda, + set_scl, + get_sda, + get_scl, + udelay, + 5, + 5 +}; + +static struct rt_i2c_bit_ops bit_ops_2 = +{ + RT_NULL, + set_sda, + set_scl, + get_sda, + get_scl, + udelay, + 5, + 5 +}; + +extern int get_pin_channel(rt_base_t pin_index); +#endif + +int rt_hw_i2c_init(void) +{ + struct rt_i2c_bus_device *busdev; + +#ifdef BSP_USING_I2C0 + static struct rt_i2c_bus_device i2c_dev0; + busdev = &i2c_dev0; + + #ifdef RT_USING_I2C_BITOPS + fpioa_set_function(BSP_I2C0_SCL_PIN, FUNC_RESV0); + fpioa_set_function(BSP_I2C0_SDA_PIN, FUNC_RESV0); + + rt_pin_write(BSP_I2C0_SCL_PIN, PIN_LOW); + rt_pin_write(BSP_I2C0_SDA_PIN, PIN_LOW); + rt_pin_mode(BSP_I2C0_SCL_PIN, PIN_MODE_INPUT_PULLUP); + rt_pin_mode(BSP_I2C0_SDA_PIN, PIN_MODE_INPUT_PULLUP); + + static pin_info_t pin0; + pin0.scl = get_pin_channel(BSP_I2C0_SCL_PIN); + pin0.sda = get_pin_channel(BSP_I2C0_SDA_PIN); + bit_ops_0.data = (void *)&pin0; + + busdev->priv = (void *)&bit_ops_0; + rt_i2c_bit_add_bus(busdev, "i2c0"); + #else + + busdev->ops = &i2c_ops; + busdev->priv = (void *)I2C0_BASE_ADDR; + + i2c_init(I2C_DEVICE_0, 0, 7, 100000); + rt_i2c_bus_device_register(busdev, "i2c0"); + #endif +#endif + +#ifdef BSP_USING_I2C1 + static struct rt_i2c_bus_device i2c_dev1; + busdev = &i2c_dev1; + + #ifdef RT_USING_I2C_BITOPS + fpioa_set_function(BSP_I2C1_SCL_PIN, FUNC_RESV0); + fpioa_set_function(BSP_I2C1_SDA_PIN, FUNC_RESV0); + + rt_pin_write(BSP_I2C1_SCL_PIN, PIN_LOW); + rt_pin_write(BSP_I2C1_SDA_PIN, PIN_LOW); + rt_pin_mode(BSP_I2C1_SCL_PIN, PIN_MODE_INPUT_PULLUP); + rt_pin_mode(BSP_I2C1_SDA_PIN, PIN_MODE_INPUT_PULLUP); + + static pin_info_t pin1; + pin1.scl = get_pin_channel(BSP_I2C1_SCL_PIN); + pin1.sda = get_pin_channel(BSP_I2C1_SDA_PIN); + bit_ops_1.data = (void *)&pin1; + + busdev->priv = (void *)&bit_ops_1; + rt_i2c_bit_add_bus(busdev, "i2c1"); + #else + + busdev->ops = &i2c_ops; + busdev->priv = (void *)I2C1_BASE_ADDR; + + i2c_init(I2C_DEVICE_1, 0, 7, 100000); + rt_i2c_bus_device_register(busdev, "i2c1"); + #endif +#endif + +#ifdef BSP_USING_I2C2 + static struct rt_i2c_bus_device i2c_dev2; + busdev = &i2c_dev2; + + #ifdef RT_USING_I2C_BITOPS + fpioa_set_function(BSP_I2C2_SCL_PIN, FUNC_RESV0); + fpioa_set_function(BSP_I2C2_SDA_PIN, FUNC_RESV0); + + rt_pin_write(BSP_I2C2_SCL_PIN, PIN_LOW); + rt_pin_write(BSP_I2C2_SDA_PIN, PIN_LOW); + rt_pin_mode(BSP_I2C2_SCL_PIN, PIN_MODE_INPUT_PULLUP); + rt_pin_mode(BSP_I2C2_SDA_PIN, PIN_MODE_INPUT_PULLUP); + + static pin_info_t pin2; + pin2.scl = get_pin_channel(BSP_I2C2_SCL_PIN); + pin2.sda = get_pin_channel(BSP_I2C2_SDA_PIN); + bit_ops_2.data = (void *)&pin2; + + busdev->priv = (void *)&bit_ops_2; + rt_i2c_bit_add_bus(busdev, "i2c2"); + #else + + busdev->ops = &i2c_ops; + busdev->priv = (void *)I2C2_BASE_ADDR; + + i2c_init(I2C_DEVICE_2, 0, 7, 100000); + rt_i2c_bus_device_register(busdev, "i2c2"); + #endif +#endif + return 0; +} +INIT_BOARD_EXPORT(rt_hw_i2c_init); +#endif diff --git a/bsp/k210/drivers/drv_io_config.c b/bsp/k210/drivers/drv_io_config.c index 253749d1f2..7211f5c4ff 100644 --- a/bsp/k210/drivers/drv_io_config.c +++ b/bsp/k210/drivers/drv_io_config.c @@ -87,14 +87,14 @@ static int print_io_config() { int i; rt_kprintf("IO Configuration Table\n"); - rt_kprintf("┌───────┬────────────────────────┐\n"); - rt_kprintf("│Pin │Function │\n"); - rt_kprintf("├───────┼────────────────────────┤\n"); + rt_kprintf("+-------+------------------------+\n"); + rt_kprintf("|Pin |Function |\n"); + rt_kprintf("+-------+------------------------+\n"); for(i = 0; i < sizeof io_config / sizeof io_config[0]; i++) { - rt_kprintf("│%-2d │%-24.24s│\n", io_config[i].io_num, io_config[i].func_name); + rt_kprintf("|%-2d |%-24.24s|\n", io_config[i].io_num, io_config[i].func_name); } - rt_kprintf("└───────┴────────────────────────┘\n"); + rt_kprintf("+-------+------------------------+\n"); return 0; } MSH_CMD_EXPORT_ALIAS(print_io_config, io, print io config);