Skip to content

I2C驱动测试

本章介绍I2C驱动的编译、模块加载、功能测试方法以及常见问题的解决方案。

编译I2C驱动

1. 内核源码树编译

如果I2C驱动是内核源码的一部分,可以通过以下步骤编译:

bash
# 进入内核源码目录
cd /usr/src/linux

# 配置内核,确保I2C支持和相关驱动选项被启用
make menuconfig

# 启用I2C支持
Device Drivers  --->
    <*> I2C support  --->
        <*>   I2C device interface
        [*]   Enhanced I2C debugging messages

# 启用I2C设备驱动
Device Drivers  --->
    <*> I2C support  --->
        <*>   I2C Hardware Bus support  --->
            <*>   <Your I2C Bus Driver>
        <*>   Miscellaneous I2C Chip support  --->
            <*>   <Your I2C Device Driver>

# 编译内核和模块
make -j$(nproc)

# 安装内核和模块
make modules_install
make install

2. 独立模块编译

如果I2C驱动是独立开发的,可以使用Makefile进行编译:

makefile
obj-m += i2c_driver.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

编译命令:

bash
make

加载I2C驱动

1. 加载驱动模块

bash
# 加载I2C核心模块
modprobe i2c-core

# 加载I2C设备接口模块
modprobe i2c-dev

# 加载I2C总线驱动模块
modprobe i2c-<bus-type>

# 加载I2C设备驱动模块
insmod i2c_driver.ko

# 查看模块是否加载成功
lsmod | grep i2c

2. 自动加载驱动

可以通过以下方式实现驱动的自动加载:

  1. 添加到模块依赖文件
    bash

echo "i2c_driver" >> /etc/modules


2. **使用设备树(适用于嵌入式系统)**:
   在设备树中添加I2C设备节点:
   ```dts
   &i2c1 {
       status = "okay";
       
       my_i2c_device@50 {
           compatible = "my,vendor,i2c-device";
           reg = <0x50>;
       };
   };

I2C设备检测

1. 查看I2C总线

bash
# 查看系统中的I2C总线
ls /dev/i2c*

# 查看I2C适配器信息
cat /sys/class/i2c-dev/

2. 扫描I2C设备

bash
# 安装i2c-tools
sudo apt-get install i2c-tools

# 扫描I2C总线上的设备
sudo i2cdetect -y 1

参数说明:

  • -y:禁用交互式提示
  • 1:I2C总线编号

功能测试

1. 使用i2c-tools测试

bash
# 读取I2C设备寄存器
sudo i2cget -y 1 0x50 0x00

# 写入I2C设备寄存器
sudo i2cset -y 1 0x50 0x00 0x12

# 读取多个连续寄存器
sudo i2cget -y 1 0x50 0x00 b

# 写入多个连续寄存器
sudo i2cset -y 1 0x50 0x00 0x12 0x34 0x56 i

参数说明:

  • -y:禁用交互式提示
  • 1:I2C总线编号
  • 0x50:I2C设备地址
  • 0x00:寄存器地址
  • b:读取字节
  • i:写入整数(4字节)

2. 使用用户空间程序测试

以下是一个简单的I2C测试程序:

c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define I2C_BUS 1
#define I2C_ADDR 0x50

int main(void)
{
    int fd;
    char buf[10];

    /* 打开I2C设备 */
    fd = open("/dev/i2c-1", O_RDWR);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    /* 设置I2C从设备地址 */
    if (ioctl(fd, I2C_SLAVE, I2C_ADDR) < 0) {
        perror("ioctl");
        close(fd);
        return 1;
    }

    /* 写入数据 */
    buf[0] = 0x00; /* 寄存器地址 */
    buf[1] = 0x12; /* 数据 */
    if (write(fd, buf, 2) != 2) {
        perror("write");
        close(fd);
        return 1;
    }

    /* 读取数据 */
    buf[0] = 0x00; /* 寄存器地址 */
    if (write(fd, buf, 1) != 1) {
        perror("write");
        close(fd);
        return 1;
    }

    if (read(fd, buf, 1) != 1) {
        perror("read");
        close(fd);
        return 1;
    }

    printf("Read value: 0x%02X\n", buf[0]);

    /* 关闭设备 */
    close(fd);

    return 0;
}

编译和运行:

bash
gcc i2c_test.c -o i2c_test
sudo ./i2c_test

性能测试

1. 传输速度测试

bash
# 测试I2C传输速度
sudo i2cget -y 1 0x50 0x00 > /dev/null

可以使用time命令测量传输时间:

bash
time for i in {1..100}; do sudo i2cget -y 1 0x50 0x00 > /dev/null; done

2. 稳定性测试

bash
# 长时间稳定性测试
for i in {1..1000}; do 
    sudo i2cget -y 1 0x50 0x00 > /dev/null;
    if [ $? -ne 0 ]; then
        echo "Error at iteration $i";
        break;
    fi;
done

调试I2C驱动

1. 内核日志查看

bash
# 查看I2C相关的内核日志
dmesg | grep -i i2c

# 实时查看内核日志
journalctl -k -f | grep -i i2c

2. 启用I2C调试

bash
# 启用I2C核心调试
echo 1 > /sys/module/i2c_core/parameters/debug

# 启用I2C总线驱动调试
echo 1 > /sys/module/i2c_<bus-type>/parameters/debug

3. I2C调试工具

  • i2cdetect:扫描I2C总线上的设备
  • i2cget:读取I2C设备寄存器
  • i2cset:写入I2C设备寄存器
  • i2cdump:转储I2C设备寄存器内容
  • i2ctransfer:执行复杂的I2C传输

4. 调试I2C驱动的常见问题

  1. 设备无法被检测到

    • 检查I2C总线是否正常工作
    • 检查设备地址是否正确
    • 检查设备的电源供应是否充足
  2. 数据传输失败

    • 检查I2C总线的时钟频率是否正确
    • 检查SDA和SCL线路是否有短路或断路
    • 检查设备的寄存器地址是否正确
  3. 驱动模块加载失败

    • 检查内核版本是否匹配
    • 检查模块依赖是否满足
    • 检查编译选项是否正确
  4. 设备探测失败

    • 检查设备树中的compatible属性是否匹配
    • 检查I2C从设备地址是否正确
    • 检查设备是否响应I2C命令

卸载I2C驱动

bash
# 卸载I2C设备驱动模块
rmmod i2c_driver

# 卸载I2C总线驱动模块
rmmod i2c-<bus-type>

# 卸载I2C设备接口模块
rmmod i2c-dev

# 卸载I2C核心模块
rmmod i2c-core

常见问题解决方案

1. I2C总线冲突

如果多个I2C设备使用相同的地址,可以通过以下方式解决:

  1. 修改设备地址:如果设备支持,可以通过硬件跳线或软件配置修改设备地址
  2. 使用I2C多路复用器:在总线上添加I2C多路复用器,将不同的设备连接到不同的子总线上

2. I2C时钟频率问题

如果I2C时钟频率设置不正确,可以通过以下方式解决:

bash
# 查看当前I2C时钟频率
cat /sys/bus/i2c/devices/i2c-1/clock_rate

# 修改I2C时钟频率(如果支持)
echo 400000 > /sys/bus/i2c/devices/i2c-1/clock_rate

3. I2C设备权限问题

如果普通用户无法访问I2C设备,可以通过以下方式解决:

bash
# 添加udev规则,设置设备权限
sudo cat > /etc/udev/rules.d/99-i2c-dev.rules << EOF
KERNEL=="i2c-[0-9]*", GROUP="i2c", MODE="0660"
EOF

# 将用户添加到i2c组
sudo usermod -aG i2c $USER

# 重新加载udev规则
sudo udevadm control --reload-rules
sudo udevadm trigger

总结

I2C驱动测试是确保驱动正常工作的重要步骤。通过本章介绍的编译、加载、测试和调试方法,可以有效地开发和调试I2C驱动。在测试过程中,应该注意观察内核日志,使用适当的调试工具,及时发现和解决问题。

此外,还应该根据具体I2C设备的特点,设计专门的测试用例,确保驱动在各种情况下都能正常工作。