From 651bb341f89a7ba24a13e3d3e417eb83fc9614b5 Mon Sep 17 00:00:00 2001 From: MacRsh Date: Tue, 14 Nov 2023 21:01:04 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=AE=8C=E5=96=84I2C=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/wch/ch32v30x/drv_i2c.c | 190 +++++++++++++++++++++++++++++++++++-- dev/i2c.c | 28 +++--- dev/i2c.h | 5 +- 3 files changed, 204 insertions(+), 19 deletions(-) diff --git a/bsp/wch/ch32v30x/drv_i2c.c b/bsp/wch/ch32v30x/drv_i2c.c index 128b0aa..9267b3c 100644 --- a/bsp/wch/ch32v30x/drv_i2c.c +++ b/bsp/wch/ch32v30x/drv_i2c.c @@ -10,6 +10,10 @@ #ifdef MR_USING_I2C +#if !defined(MR_USING_I2C1) && !defined(MR_USING_I2C2) +#error "Please define at least one I2C macro like MR_USING_I2C1. Otherwise undefine MR_USING_I2C." +#endif + enum drv_i2c_index { #ifdef MR_USING_I2C1 @@ -20,7 +24,7 @@ enum drv_i2c_index #endif /* MR_USING_I2C2 */ }; -static const char *i2c_name[] = +static const char *i2c_bus_name[] = { #ifdef MR_USING_I2C1 "i2c1", @@ -42,7 +46,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] = GPIO_Pin_6, GPIOB, GPIO_Pin_7, - I2C1_IRQn, + I2C1_EV_IRQn, 0 }, #elif (MR_CFG_I2C1_GROUP == 2) @@ -54,7 +58,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] = GPIO_Pin_8, GPIOB, GPIO_Pin_9, - I2C1_IRQn, + I2C1_EV_IRQn, GPIO_Remap_I2C1 }, #else @@ -71,7 +75,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] = GPIO_Pin_10, GPIOB, GPIO_Pin_11, - I2C2_IRQn, + I2C2_EV_IRQn, 0 } #else @@ -87,10 +91,11 @@ static int drv_i2c_bus_configure(struct mr_i2c_bus *i2c_bus, struct mr_i2c_confi struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; int state = (config->baud_rate == 0) ? DISABLE : ENABLE; GPIO_InitTypeDef GPIO_InitStructure = {0}; + NVIC_InitTypeDef NVIC_InitStructure = {0}; I2C_InitTypeDef I2C_InitStructure = {0}; RCC_APB2PeriphClockCmd(i2c_bus_data->gpio_clock, ENABLE); - RCC_APB2PeriphClockCmd(i2c_bus_data->clock, state); + RCC_APB1PeriphClockCmd(i2c_bus_data->clock, state); /* Configure remap */ if (i2c_bus_data->remap != 0) @@ -121,7 +126,7 @@ static int drv_i2c_bus_configure(struct mr_i2c_bus *i2c_bus, struct mr_i2c_confi case MR_I2C_ADDR_BITS_10: { - I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; + I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; break; } @@ -154,6 +159,13 @@ static int drv_i2c_bus_configure(struct mr_i2c_bus *i2c_bus, struct mr_i2c_confi NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = state; NVIC_Init(&NVIC_InitStructure); + if (config->host_slave == MR_I2C_HOST) + { + I2C_ITConfig(i2c_bus_data->instance, I2C_IT_EVT, DISABLE); + } else + { + I2C_ITConfig(i2c_bus_data->instance, I2C_IT_EVT, state); + } /* Configure I2C */ I2C_InitStructure.I2C_ClockSpeed = config->baud_rate; @@ -166,4 +178,170 @@ static int drv_i2c_bus_configure(struct mr_i2c_bus *i2c_bus, struct mr_i2c_confi return MR_EOK; } +static void drv_i2c_bus_start(struct mr_i2c_bus *i2c_bus) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + int i = 0; + + I2C_GenerateSTART(i2c_bus_data->instance, ENABLE); + while (I2C_CheckEvent(i2c_bus_data->instance, I2C_EVENT_MASTER_MODE_SELECT) == RESET) + { + i++; + if (i > UINT16_MAX) + { + return; + } + } +} + +static void drv_i2c_bus_send_addr(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + int i = 0; + + I2C_SendData(i2c_bus_data->instance, addr); + while (I2C_CheckEvent(i2c_bus_data->instance, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == RESET) + { + i++; + if (i > UINT16_MAX) + { + return; + } + } + + if (addr_bits == MR_I2C_ADDR_BITS_10) + { + I2C_SendData(i2c_bus_data->instance, (addr >> 8)); + i = 0; + while (I2C_CheckEvent(i2c_bus_data->instance, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == RESET) + { + i++; + if (i > UINT16_MAX) + { + return; + } + } + } +} + +static void drv_i2c_bus_stop(struct mr_i2c_bus *i2c_bus) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + + I2C_GenerateSTOP(i2c_bus_data->instance, ENABLE); +} + +static ssize_t drv_i2c_bus_read(struct mr_i2c_bus *i2c_bus, uint8_t *buf, size_t size) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + ssize_t rd_size = 0; + + for (rd_size = 0; rd_size < size; rd_size++) + { + int i = 0; + + /* Read data */ + while (I2C_CheckEvent(i2c_bus_data->instance, I2C_EVENT_MASTER_BYTE_RECEIVED) == RESET); + { + i++; + if (i > UINT16_MAX) + { + return rd_size; + } + } + buf[rd_size] = I2C_ReceiveData(i2c_bus_data->instance); + } + return rd_size; +} + +static ssize_t drv_i2c_bus_write(struct mr_i2c_bus *i2c_bus, const uint8_t *buf, size_t size) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + ssize_t wr_size = 0; + + for (wr_size = 0; wr_size < size; wr_size++) + { + int i = 0; + + /* Write data */ + I2C_SendData(i2c_bus_data->instance, buf[wr_size]); + while (I2C_CheckEvent(i2c_bus_data->instance, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == RESET) + { + i++; + if (i > UINT16_MAX) + { + return wr_size; + } + } + } + return wr_size; +} + +static void drv_i2c_bus_isr(struct mr_i2c_bus *i2c_bus) +{ + struct drv_i2c_bus_data *i2c_bus_data = (struct drv_i2c_bus_data *)i2c_bus->dev.drv->data; + + if (I2C_GetITStatus(i2c_bus_data->instance, I2C_IT_RXNE) != RESET) + { + mr_dev_isr(&i2c_bus->dev, MR_ISR_EVENT_RD_INTER, NULL); + I2C_ClearITPendingBit(i2c_bus_data->instance, I2C_IT_RXNE); + } +} + +#ifdef MR_USING_I2C1 +void I2C1_EV_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); +void I2C1_EV_IRQHandler(void) +{ + drv_i2c_bus_isr(&i2c_bus_dev[DRV_INDEX_I2C1]); +} +#endif /* MR_USING_I2C1 */ + +#ifdef MR_USING_I2C2 +void I2C2_EV_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); +void I2C2_EV_IRQHandler(void) +{ + drv_i2c_bus_isr(&i2c_bus_dev[DRV_INDEX_I2C2]); +} +#endif /* MR_USING_I2C2 */ + +static struct mr_i2c_bus_ops i2c_bus_drv_ops = + { + drv_i2c_bus_configure, + drv_i2c_bus_start, + drv_i2c_bus_send_addr, + drv_i2c_bus_stop, + drv_i2c_bus_read, + drv_i2c_bus_write, + }; + +static struct mr_drv i2c_bus_drv[mr_array_num(i2c_bus_drv_data)] = + { +#ifdef MR_USING_I2C1 + { + Mr_Dev_Type_I2c, + &i2c_bus_drv_ops, + &i2c_bus_drv_data[DRV_INDEX_I2C1] + }, +#endif /* MR_USING_I2C1 */ +#ifdef MR_USING_I2C2 + { + Mr_Dev_Type_I2c, + &i2c_bus_drv_ops, + &i2c_bus_drv_data[DRV_INDEX_I2C2] + }, +#endif /* MR_USING_I2C2 */ + }; + +int drv_i2c_bus_init(void) +{ + int index = 0; + + for (index = 0; index < mr_array_num(i2c_bus_dev); index++) + { + mr_i2c_bus_register(&i2c_bus_dev[index], i2c_bus_name[index], &i2c_bus_drv[index]); + } + return MR_EOK; +} +MR_INIT_DRV_EXPORT(drv_i2c_bus_init); + #endif /* MR_USING_I2C */ diff --git a/dev/i2c.c b/dev/i2c.c index 8c2912b..52f6ae7 100644 --- a/dev/i2c.c +++ b/dev/i2c.c @@ -17,20 +17,25 @@ MR_INLINE void i2c_bus_send_addr(struct mr_i2c_bus *i2c_bus, int rdwr) { struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)i2c_bus->dev.drv->ops; struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)i2c_bus->owner; - uint8_t addr[2] = {0, 0}; + int addr = 0; if (i2c_dev != MR_NULL) { - addr[1] = ((i2c_dev->addr >> 3) & 0x7f); - addr[0] = ((i2c_dev->addr >> 1) & 0x07) | 0x80; + if (i2c_dev->addr_bits == MR_I2C_ADDR_BITS_7) + { + addr = i2c_dev->addr; + } else + { + addr = ((0xf0 | ((i2c_dev->addr >> 7) & 0x06)) << 8) | (i2c_dev->addr & 0xff); + } + } + if (rdwr == MR_I2C_RD) + { + addr |= 0x01; } ops->start(i2c_bus); - if (rdwr == MR_I2C_RD) - { - addr[1] |= 0x01; - } - ops->write(i2c_bus, &addr, (i2c_dev->addr_bits >> 3) + 1); + ops->send_addr(i2c_bus, addr, i2c_dev->addr_bits); } static int mr_i2c_bus_open(struct mr_dev *dev) @@ -60,7 +65,7 @@ static ssize_t mr_i2c_bus_read(struct mr_dev *dev, int off, void *buf, size_t si if (off >= 0) { i2c_bus_send_addr(i2c_bus, MR_I2C_WR); - ops->write(i2c_bus, &off, i2c_bus->config.off_bits); + ops->write(i2c_bus, (uint8_t *)&off, i2c_bus->config.off_bits); } i2c_bus_send_addr(i2c_bus, MR_I2C_RD); @@ -83,7 +88,7 @@ static ssize_t mr_i2c_bus_write(struct mr_dev *dev, int off, const void *buf, si i2c_bus_send_addr(i2c_bus, MR_I2C_WR); if (off >= 0) { - ops->write(i2c_bus, &off, i2c_bus->config.off_bits); + ops->write(i2c_bus, (uint8_t *)&off, i2c_bus->config.off_bits); } ssize_t ret = ops->write(i2c_bus, buf, size); @@ -229,7 +234,8 @@ MR_INLINE int i2c_dev_take_bus(struct mr_i2c_dev *i2c_dev) if (i2c_dev->config.baud_rate != i2c_bus->config.baud_rate || i2c_dev->config.host_slave != i2c_bus->config.host_slave) { - int ret = ops->configure(i2c_bus, &i2c_dev->config, i2c_dev->addr, i2c_dev->addr_bits); + int addr = (i2c_dev->config.host_slave == MR_I2C_SLAVE) ? i2c_dev->addr : 0x01; + int ret = ops->configure(i2c_bus, &i2c_dev->config, addr, i2c_dev->addr_bits); if (ret != MR_EOK) { return ret; diff --git a/dev/i2c.h b/dev/i2c.h index 2c390d7..a0ec914 100644 --- a/dev/i2c.h +++ b/dev/i2c.h @@ -69,9 +69,10 @@ struct mr_i2c_bus_ops { int (*configure)(struct mr_i2c_bus *i2c_bus, struct mr_i2c_config *config, int addr, int addr_bits); void (*start)(struct mr_i2c_bus *i2c_bus); + void (*send_addr)(struct mr_i2c_bus *i2c_bus, int addr, int addr_bits); void (*stop)(struct mr_i2c_bus *i2c_bus); - ssize_t (*write)(struct mr_i2c_bus *i2c_bus, const void *buf, size_t size); - ssize_t (*read)(struct mr_i2c_bus *i2c_bus, void *buf, size_t size); + ssize_t (*read)(struct mr_i2c_bus *i2c_bus, uint8_t *buf, size_t size); + ssize_t (*write)(struct mr_i2c_bus *i2c_bus, const uint8_t *buf, size_t size); }; /**