I2C 驱动

基于 lisa_device 框架的 I2C 设备驱动,为 ARCS 平台提供统一的 I2C 通信接口。

功能特性

  • 设备支持: I2C0、I2C1 两个独立的 I2C 控制器,可独立配置和使用

  • 灵活配置: 可选择性启用 I2C0 或 I2C1,节省资源

  • 主机模式: 支持标准模式(100kHz)、快速模式(400kHz)、快速增强模式(1MHz)

  • 传输接口: 支持单次读写和组合传输(写后读)

  • 设备探测: 支持 0 字节传输进行设备探测

  • 线程安全: 内部使用互斥锁保护并发访问

配置选项

prj.conf 中启用驱动:

CONFIG_LISA_I2C=y          # 使能 I2C 驱动框架
CONFIG_LISA_I2C0=y         # 使能 I2C0 控制器(可选)
CONFIG_LISA_I2C1=y         # 使能 I2C1 控制器(可选)

注意: 根据应用需求选择启用对应的 I2C 控制器,未启用的控制器不会编译进代码。

API 接口

配置接口

int lisa_i2c_configure(lisa_device_t *dev, const lisa_i2c_config_t *config);
int lisa_i2c_get_config(lisa_device_t *dev, lisa_i2c_config_t *config);

传输接口

int lisa_i2c_transfer(lisa_device_t *dev, lisa_i2c_msg_t *msgs, uint32_t num_msgs);
int lisa_i2c_write(lisa_device_t *dev, uint16_t addr, const uint8_t *buf, uint32_t len);
int lisa_i2c_read(lisa_device_t *dev, uint16_t addr, uint8_t *buf, uint32_t len);

速度模式

驱动支持以下速度模式:

  • LISA_I2C_SPEED_STANDARD (100000 Hz): 标准模式

  • LISA_I2C_SPEED_FAST (400000 Hz): 快速模式

  • LISA_I2C_SPEED_FAST_PLUS (1000000 Hz): 快速增强模式

传输标志

  • LISA_I2C_FLAG_NONE: 无特殊标志(默认为写操作)

  • LISA_I2C_FLAG_READ: 读操作标志(不设置则为写操作)

  • LISA_I2C_FLAG_NO_START: 不发送 START 条件(当前实现中忽略)

  • LISA_I2C_FLAG_NO_STOP: 不发送 STOP 条件(用于组合传输)

  • LISA_I2C_FLAG_10BIT_ADDR: 使用 10 位地址模式

使用示例

基本配置和读写

#include "lisa_i2c.h"
#include "lisa_device.h"

// 1. 获取 I2C 设备
lisa_device_t *i2c_dev = lisa_device_get("i2c0");
if (!lisa_device_ready(i2c_dev)) {
    printf("Error: i2c0 device not ready\n");
    return -1;
}

// 2. 配置 I2C 总线(可选,默认为标准模式)
lisa_i2c_config_t config = {
    .speed = LISA_I2C_SPEED_FAST,  // 400kHz
    .master_mode = true,
    .slave_addr = 0
};
lisa_i2c_configure(i2c_dev, &config);

// 3. 写入数据
uint8_t write_data[] = {0x01, 0x02, 0x03};
int ret = lisa_i2c_write(i2c_dev, 0x50, write_data, sizeof(write_data));
if (ret != 0) {
    printf("Write failed: %d\n", ret);
}

// 4. 读取数据
uint8_t read_data[4];
ret = lisa_i2c_read(i2c_dev, 0x50, read_data, sizeof(read_data));
if (ret != 0) {
    printf("Read failed: %d\n", ret);
}

组合传输(写后读)

// 使用 transfer 接口实现写后读操作
lisa_i2c_msg_t msgs[2];

// 第一个消息:写入寄存器地址
uint8_t reg_addr = 0x01;
msgs[0].addr = 0x50;
msgs[0].flags = LISA_I2C_FLAG_NO_STOP;  // 写操作,不发送 STOP,继续传输
msgs[0].len = 1;
msgs[0].buf = &reg_addr;

// 第二个消息:读取数据
uint8_t read_buf[4];
msgs[1].addr = 0x50;
msgs[1].flags = LISA_I2C_FLAG_READ;     // 读操作标志
msgs[1].len = sizeof(read_buf);
msgs[1].buf = read_buf;

int ret = lisa_i2c_transfer(i2c_dev, msgs, 2);
if (ret != 0) {
    printf("Transfer failed: %d\n", ret);
}

设备探测

// 使用 0 字节传输探测设备是否存在
lisa_i2c_msg_t msg = {
    .addr = 0x50,
    .flags = LISA_I2C_FLAG_NONE,
    .len = 0,      // 0 字节传输
    .buf = NULL
};

int ret = lisa_i2c_transfer(i2c_dev, &msg, 1);
if (ret == LISA_DEVICE_OK) {
    printf("Device found at address 0x50\n");
} else if (ret == LISA_DEVICE_ERR_NACK) {
    printf("No device at address 0x50\n");
}

硬件配置

引脚复用配置

I2C 驱动在初始化时会自动调用板型目录中定义的 lisa_i2c0_pinmux()lisa_i2c1_pinmux() 函数,用于配置 I2C 引脚的复用功能。

配置位置:

  • 定义: boards/<板型名>/pinmux.c 中实现 lisa_i2c0_pinmux()lisa_i2c1_pinmux() 函数

  • 声明: boards/<板型名>/pinmux.h 中声明函数

  • 调用时机: I2C0/I2C1 设备初始化时自动调用

示例 (参考 boards/arcs_evb/pinmux.c):

void lisa_i2c0_pinmux()
{
    /* I2C0: PA22=SDA, PA23=SCL, 功能码 8 */
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 22, 8);
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_A, 23, 8);
}

void lisa_i2c1_pinmux()
{
    /* I2C1: PB0=SCL, PB1=SDA, 功能码 9 */
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_B, 0, 9);
    IOMuxManager_PinConfigure(CSK_IOMUX_PAD_B, 1, 9);
}

注意:

  • 该函数由板型相关代码实现,不同板型的引脚配置可能不同

  • 只需配置实际使用的 I2C 控制器引脚

  • I2C 功能码通常为 8 或 9,具体请参考芯片手册

  • 如需自定义引脚配置,可在 sample 中重写 pinmux 函数(参考 samples/drivers/devices/lisa_uart/poll_in/src/main.c

注意事项

  1. 引脚配置: 使用 I2C 前需要先配置对应的 GPIO 引脚为 I2C 功能,驱动初始化时会自动调用 pinmux 函数

  2. 设备选择: 使用前需在 prj.conf 中启用对应的 I2C 控制器

  3. 设备初始化: 系统启动时会自动初始化已启用的 I2C 设备

  4. 线程安全: 驱动内部已实现线程保护,可在多线程环境中使用

  5. 超时处理: 所有传输操作都有 1 秒的超时限制

  6. 错误处理:

    • LISA_DEVICE_ERR_NACK: 从机无应答(设备不存在或地址错误)

    • LISA_DEVICE_ERR_TIMEOUT: 传输超时

    • LISA_DEVICE_ERR_IO: 硬件 IO 错误

  7. transfer 函数使用:

    • 支持读写操作,通过 LISA_I2C_FLAG_READ 标志区分

    • 支持组合传输(使用 LISA_I2C_FLAG_NO_STOP 实现写后读)

    • 支持 0 字节传输进行设备探测

    • 简单读写建议使用 lisa_i2c_read()lisa_i2c_write() 函数

  8. 引脚上拉: I2C 总线需要外接上拉电阻(通常 4.7kΩ),或确认开发板已提供默认上拉

  9. 设备探测: 使用 0 字节传输(len=0)进行设备探测时,驱动会严格检查 ACK 响应,确保探测结果准确

文件说明

  • lisa_i2c.h - 驱动头文件,包含所有 API 和类型定义

  • lisa_i2c_arcs.c - ARCS 平台适配实现

  • CMakeLists.txt - 构建配置

  • Kconfig - 配置选项

  • README.md - 驱动使用说明

示例程序

完整的示例程序位于:

  • samples/drivers/devices/lisa_i2c/basic_write_read/ - I2C 基础读写示例

    • 演示 lisa_i2c_write() API 用法

    • 演示 lisa_i2c_read() API 用法

    • 演示 lisa_i2c_transfer() 组合传输用法

  • samples/drivers/devices/lisa_i2c/slave_scan/ - I2C 从机扫描示例

    • 扫描 I2C 总线上的所有从机地址

    • 检测已连接的 I2C 设备