1.完善I2C框架。

This commit is contained in:
MacRsh
2023-11-14 21:01:04 +08:00
parent 400defd26a
commit 651bb341f8
3 changed files with 204 additions and 19 deletions

View File

@@ -10,6 +10,10 @@
#ifdef MR_USING_I2C #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 enum drv_i2c_index
{ {
#ifdef MR_USING_I2C1 #ifdef MR_USING_I2C1
@@ -20,7 +24,7 @@ enum drv_i2c_index
#endif /* MR_USING_I2C2 */ #endif /* MR_USING_I2C2 */
}; };
static const char *i2c_name[] = static const char *i2c_bus_name[] =
{ {
#ifdef MR_USING_I2C1 #ifdef MR_USING_I2C1
"i2c1", "i2c1",
@@ -42,7 +46,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] =
GPIO_Pin_6, GPIO_Pin_6,
GPIOB, GPIOB,
GPIO_Pin_7, GPIO_Pin_7,
I2C1_IRQn, I2C1_EV_IRQn,
0 0
}, },
#elif (MR_CFG_I2C1_GROUP == 2) #elif (MR_CFG_I2C1_GROUP == 2)
@@ -54,7 +58,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] =
GPIO_Pin_8, GPIO_Pin_8,
GPIOB, GPIOB,
GPIO_Pin_9, GPIO_Pin_9,
I2C1_IRQn, I2C1_EV_IRQn,
GPIO_Remap_I2C1 GPIO_Remap_I2C1
}, },
#else #else
@@ -71,7 +75,7 @@ static struct drv_i2c_bus_data i2c_bus_drv_data[] =
GPIO_Pin_10, GPIO_Pin_10,
GPIOB, GPIOB,
GPIO_Pin_11, GPIO_Pin_11,
I2C2_IRQn, I2C2_EV_IRQn,
0 0
} }
#else #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; 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; int state = (config->baud_rate == 0) ? DISABLE : ENABLE;
GPIO_InitTypeDef GPIO_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
I2C_InitTypeDef I2C_InitStructure = {0}; I2C_InitTypeDef I2C_InitStructure = {0};
RCC_APB2PeriphClockCmd(i2c_bus_data->gpio_clock, ENABLE); RCC_APB2PeriphClockCmd(i2c_bus_data->gpio_clock, ENABLE);
RCC_APB2PeriphClockCmd(i2c_bus_data->clock, state); RCC_APB1PeriphClockCmd(i2c_bus_data->clock, state);
/* Configure remap */ /* Configure remap */
if (i2c_bus_data->remap != 0) 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: case MR_I2C_ADDR_BITS_10:
{ {
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit;
break; 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_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = state; NVIC_InitStructure.NVIC_IRQChannelCmd = state;
NVIC_Init(&NVIC_InitStructure); 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 */ /* Configure I2C */
I2C_InitStructure.I2C_ClockSpeed = config->baud_rate; 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; 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 */ #endif /* MR_USING_I2C */

View File

@@ -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_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; 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) if (i2c_dev != MR_NULL)
{ {
addr[1] = ((i2c_dev->addr >> 3) & 0x7f); if (i2c_dev->addr_bits == MR_I2C_ADDR_BITS_7)
addr[0] = ((i2c_dev->addr >> 1) & 0x07) | 0x80; {
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); ops->start(i2c_bus);
if (rdwr == MR_I2C_RD) ops->send_addr(i2c_bus, addr, i2c_dev->addr_bits);
{
addr[1] |= 0x01;
}
ops->write(i2c_bus, &addr, (i2c_dev->addr_bits >> 3) + 1);
} }
static int mr_i2c_bus_open(struct mr_dev *dev) 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) if (off >= 0)
{ {
i2c_bus_send_addr(i2c_bus, MR_I2C_WR); 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); 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); i2c_bus_send_addr(i2c_bus, MR_I2C_WR);
if (off >= 0) 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); 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 if (i2c_dev->config.baud_rate != i2c_bus->config.baud_rate
|| i2c_dev->config.host_slave != i2c_bus->config.host_slave) || 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) if (ret != MR_EOK)
{ {
return ret; return ret;

View File

@@ -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); 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 (*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); 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, uint8_t *buf, size_t size);
ssize_t (*read)(struct mr_i2c_bus *i2c_bus, void *buf, size_t size); ssize_t (*write)(struct mr_i2c_bus *i2c_bus, const uint8_t *buf, size_t size);
}; };
/** /**