跳到主要内容

TWI - 模块使用说明

本章节主要描述 TWI (I2C) 模块的常见功能配置和使用。

环境配置

软件环境

  • 使用 V821 SDK,选择 v821-ipc-tina 方案。
  • 相关源码路径:
bsp/drivers/twi/twi-sunxi.c

硬件环境

  • 使用 v821 ipc开发板
  • 测试使用的 I2C 设备为 eeprom,连接到 i2c0,涉及 PA10PA11 两个 GPIO 引脚。
  • 注意外设的供电、GND、I2C 引脚的硬件连接。

驱动配置

  1. 执行 make kernel_menuconfig
  2. 选择以下配置项:
Allwinner BSP --->
Device Drivers --->
TWI Drivers --->
<*> I2C Support for Allwinner SoCs

DTS 配置

使用对应的 TWI 通道前,需要在 board.dts 文件中配置 TWI 引脚和状态:

  1. 进入 device/config/chips/v821/configs/ipc/linux-5.4-ansc 目录,编辑 board.dts 文件。

  2. 配置 twi0 引脚:

twi0_pins_default: twi0@0 {
pins = "PA10", "PA11";
function = "twi0";
drive-strength = <10>;
bias-pull-up;
};

twi0_pins_sleep: twi0@1 {
pins = "PA10", "PA11";
function = "gpio_in";
};
  1. 配置 twi0 设备:
&twi0 {
clock-frequency = <400000>;
pinctrl-0 = <&twi0_pins_default>;
pinctrl-1 = <&twi0_pins_sleep>;
pinctrl-names = "default", "sleep";
twi_drv_used = <1>; /* 推荐设置为 1,以确保稳定性和向后兼容性 */
status = "okay";
};

软件包配置

  1. 执行 make menuconfig
  2. 选中以下 I2C 测试工具软件包配置:
CONFIG_BUSYBOX_CONFIG_I2CGET=y
CONFIG_BUSYBOX_CONFIG_I2CSET=y
CONFIG_BUSYBOX_CONFIG_I2CDUMP=y
CONFIG_BUSYBOX_CONFIG_I2CDETECT=y
CONFIG_BUSYBOX_CONFIG_I2CTRANSFER=y

模块功能测试

TWI0 基本功能测试

用例名称: TWI0 控制器下对 I2C 设备进行读写功能测试

功能说明: I2C 设备读写功能测试

前置条件:

  1. 设置 驱动配置;
  2. 配置 TWI0 控制器的 DTS 节点;
  3. 开启 I2C 测试工具软件包并编译固件;
  4. TWI0 控制器引脚连接到 EEPROM 外设。

操作步骤:

  1. 烧录固件。
  2. 输入命令查看当前 TWI 通路:i2cdetect -l
  3. 输入命令查看外接设备;
  4. 使用 i2ctools 工具成功进行读写通信。

预期结果:

  1. 烧录固件后,系统成功启动;
  2. 成功获取到 TWI0 通路;
  3. 成功识别到外接设备;
  4. 成功与外设进行 TWI 读写通信测试。

关键 LOG 如下:

1.查看当前TWI通路:
root@(none):/# i2cdetect -l
i2c-0 i2c SUNXI TWI(0x0000000042502000) I2C adapter

2.识别当前TWI外设:
root@(none):/# i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

3.读取当前外设寄存器值:
root@(none):/# i2cdump -f -y 0 0x50
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

4.修改外设寄存器值,再读取外设寄存器值:
root@(none):/# i2cset -f -y 0 0x50 0x10 0xff
root@(none):/# i2cget -f -y 0 0x50 0x10
0xff
root@(none):/# i2cdump -f -y 0 0x50
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
10: ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

400K/200K/100K 频率下 TWI 通信

用例名称: 验证 400K/200K/100K 频率下 TWI 通信

功能说明: 验证在 400K、200K 和 100K 频率下 TWI 通信的稳定性和功能。

前置条件:

  • 设置驱动配置;
  • 配置 TWI0 控制器的 DTS 节点;
  • 开启 I2C 测试工具软件包并编译固件;
  • TWI0 控制器引脚连接到地址为 0x50 的 EEPROM 外设。

操作步骤:

  • 上电进入 Linux 系统控制台。
  • 在 Linux 系统控制台执行命令:cat /sys/devices/platform/soc@2002000/42502000.twi0/info,查看 TWI0 控制器时钟频率。
  • 在 Linux 系统控制台执行命令:i2cdetect -y 0,检测 TWI 总线上连接的外设。
  • 在 Linux 系统控制台执行命令:i2cget -f -y 0 0x50 0x10,读取 EEPROM 设备 0x10 地址处的数据。
  • 在 Linux 系统控制台执行命令:i2cset -f -y 0 0x50 0x10 0xab,向 EEPROM 设备 0x10 地址处写入 0xab
  • 在 Linux 系统控制台执行命令:i2cget -f -y 0 0x50 0x10,读取 EEPROM 设备 0x10 地址处的数据。
  • 在 Linux 系统控制台执行命令:i2cset -f -y 0 0x50 0x10 0x00,向 EEPROM 设备 0x10 地址处写入 0x00
  • 在 Linux 系统控制台执行命令:echo 200000 > /sys/devices/platform/soc@3000000/42502000.twi0/freq,设置 TWI0 控制器的时钟频率为 200K,并重复执行步骤 3 到步骤 8。
  • 在 Linux 系统控制台执行命令:echo 100000 > /sys/devices/platform/soc@3000000/42502000.twi0/freq,设置 TWI0 控制器的时钟频率为 100K,并重复执行步骤 3 到步骤 8。

预期结果:

  • 步骤 2 中获取到的时钟频率应为期望的时钟频率:400K、200K 和 100K。
  • 步骤 3 中能够成功检测到地址为 0x50 的 EEPROM 外设。
  • 步骤 6 中读取到的数据应为 0xab,且与步骤 4 读取到的数据值不同。

关键 LOG 如下:

1.分别将TWI频率设置成400K、200K、100K,并查看当前TWI频率:
root@(none):/# cat sys/devices/platform/soc@2002000/42502000.twi0/info
twi->bus_num = 0
twi->name = 42502000.twi0
twi->irq = 39
twi->freqency = 400000

root@(none):/# echo 200000 > /sys/devices/platform/soc@2002000/42502000.twi0/freq
[ 78.357929] sunxi:twi-42502000.twi0:[INFO]: Change clock frequncy from 400000 to 200000.
root@(none):/#
root@(none):/#
root@(none):/# cat sys/devices/platform/soc@2002000/42502000.twi0/info
twi->bus_num = 0
twi->name = 42502000.twi0
twi->irq = 39
twi->freqency = 200000
root@(none):/#

root@(none):/#
root@(none):/# echo 100000 > /sys/devices/platform/soc@2002000/42502000.twi0/freq
[ 86.487084] sunxi:twi-42502000.twi0:[INFO]: Change clock frequncy from 200000 to 100000.
root@(none):/# cat sys/devices/platform/soc@2002000/42502000.twi0/info
twi->bus_num = 0
twi->name = 42502000.twi0
twi->irq = 39
twi->freqency = 100000
root@(none):/#


2.分别在不同频率下,读写TWI外设寄存器值(如下为400K时的测试日志):

root@(none):/# i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@(none):/# i2cget -f -y 0 0x50 0x10
0x00
root@(none):/# i2cset -f -y 0 0x50 0x10 0xab
root@(none):/# i2cget -f -y 0 0x50 0x10
0xab
root@(none):/# i2cset -f -y 0 0x50 0x10 0x00

如需要默认开机就设置好频率,可修改 dts 对应 twi 节点修改,或增加配置 clock‑frequency = <400000>;

常见问题

执行 i2cdetect 出现大量报错

在执行前先将内核打印等级调低,使用命令

dmesg -n 1