7.6.5. 设计说明¶
7.6.5.1. 源码说明¶
源代码位于 bsp/artinchip/
:
bsp/artinchip/drv/i2c/drv_i2c.c,I2C Driver 层实现
bsp/artinchip/hal/i2c/hal_i2c.c,I2C HAL 层实现
bsp/artinchip/include/hal/hal_i2c.h,I2C HAL 层接口头文件
7.6.5.2. 模块架构¶
I2C 驱动 Driver 层采用 RT-Thread 的 I2C 设备驱动框架,APP 可以遵从 RT-Thread 的调用方式,也可以直接使用 HAL 层,支持 baremetal 方式的应用场景。

7.6.5.2.1. I2C master¶
I2C 作为 master 时,驱动的实现主要包括4个部分:
硬件参数配置:主要是设置 I2C 工作的主机模式,7bit 或 10bit 寻址,寻址的从机地址设置,FIFO 设置以及总线传输速率等。
SCL时序参数设置:根据设置的总线传输速率,设置 SCL 的高低电平时间。
i2c_algorithm 的实现:作为主机端,主要是 master_xfer 的实现。在驱动实现中,以 message 为单位进行数据的收发,数据的传输采用中断的方式。
中断的处理:处理 master 端的数据收发,并产生相应的 start、ack、nack、restart、stop 信号。
7.6.5.3. 关键流程设计¶
7.6.5.3.3. I2C模块总线信号¶
在 I2C 总线的数据传输过程,由 start/restart/stop 作为总线的控制信号。了解 I2C 模块中 start/restart/stop 信号的生成方式,有助于了解驱动的源码实现。
7.6.5.3.3.1. master transmitter¶

对图中3个关键点的解释:
I2C 作为 master transmitter 时,当向 TXFIFO 中写入数据时,I2C 模块会自动发出 start 信号
若 stop 位未置位,则当 TXFIFO 中的数据全部发送,TXFIFO 为空时,会保持 SCL 为低电平,直到再次向 TXFIFO 中写入数据
再次向 TXFIFO 写入数据时,将 stop 位置1,则在完成该字节的发送后,master 会自动发送 stop 信号
7.6.5.3.3.2. master receiver¶

对图中3个关键点的解释:
I2C 作为 master receiver 时,当向 TXFIFO 写入读命令(即向 I2C_DATA_CMD 写入读命令)时,I2C 模块会自动发送 start 信号
当接收到 slave 端发送的数据后,只有再次发送一次读命令,才会对本次收到的数据恢复 ACK 确认信号
master 在接收到最后一个数据后,回复 NACK,slave 端才会结束数据的传送。在发送最后一个读命令时,同时将 stop 位置位,则master在接收到slave发送的数据后,I2C模块会自动发送NACK信号
注解
I2C 模块的数据传输,无论是 transmitter 还是 receiver,都会用到 TXFIFO,transmitter 时用来发送数据,receiver 时用来发送命令。所以,中断处理中,触发 TXFIFO_EMPTY 中断的,可能是 read msg,也可能是 write msg
7.6.5.3.4. 中断流程¶

7.6.5.4. 数据结构设计¶
管理 I2C 控制器资源的顶层结构体
struct rt_i2c_bus_device
{
struct rt_device parent; // 设备基类 device
const struct rt_i2c_bus_device_ops *ops; // I2C 操作方法
rt_uint16_t flags; // I2C 读写标志
struct rt_mutex lock; // 互斥锁,保证多线程访问安全
rt_uint32_t timeout; // 超时时间
rt_uint32_t retries; // 调用次数
void *priv; // 私有数据
};
7.6.5.5. 接口设计¶
对 I2C 总线操作的结构体
struct rt_i2c_bus_device_ops
{
rt_size_t (*master_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
rt_size_t (*slave_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, rt_uint32_t, rt_uint32_t);
};
D211 实例化的结构体为:
static const struct rt_i2c_bus_device_ops i2c_ops = {
aic_i2c_master_xfer, // master_xfer
RT_NULL, // slave_xfer
aic_i2c_bus_control, // bus_control
};
I2C 消息结构体
struct rt_i2c_msg
{
rt_uint16_t addr; // I2C 从设备地址
rt_uint16_t flags; // I2C 读写标志
rt_uint16_t len; // 待传输数据的长度
rt_uint8_t *buf; // 待传输数据的指针
};
7.6.5.5.1. aic_i2c_master_xfer¶
函数原型 |
static rt_size_t aic_i2c_master_xfer(struct rt_i2c_bus_device *bus, | struct rt_i2c_msg msgs[], rt_uint32_t num) |
---|---|
功能说明 |
打印I2C发生abort的原因,并返回相应的error值 |
参数定义 |
bus:I2C 接口对应的总线指针
msgs: 发送的消息数组
num: 发送的消息数量
|
返回值 |
返回已发出的消息数量 |
注意事项 |
7.6.5.5.2. aic_i2c_bus_control¶
函数原型 |
static rt_err_t aic_i2c_bus_control(struct rt_i2c_bus_device *bus, | rt_uint32_t cmd, rt_uint32_t value) |
---|---|
功能说明 |
对 I2C 总线参数进行设置,目前支持更改总线速率,成功返回 RT_EOK |
参数定义 |
bus:I2C 接口对应的总线指针
cmd:命令参数
value:命令值
|
返回值 |
RT_EOK:函数执行成功
-RT_EIO:非法操作
|
注意事项 |