嵌入式Linux下I2C接口调试
1). 简介
I2C是嵌入式设备最为常用的接口之一,常用于如下面这些应用场景,因此本文就基于嵌入式Linux演示在User Space进行I2C设备调试。
- Digital to Analog converter
- EEPROM
- Real Time Clock
- Touch screen LCD
- Audio codec
本文所演示的平台来自于Toradex ApalisiMX6Q ARM嵌入式平台,这是一个基于NXP iMX6Q ARM处理器,支持四核心Cortex-A9。
2. 准备
a).Apalis iMX6Q ARM核心版配合Apalis Ixora载板,连接调试串口UART1到开发主机方便调试,同时配置好Ubuntu开发主机开发环境,具体操作方法可以参考这里。
b).Apalis iMX6Q系统使用Toradex Linux Release V2.6.1,下载和更新方法请参考这里。
3). I2C总线user space操作命令测试
a). Apalis iMX6Q核心版默认定义提供了三个I2C总线可供外部使用(i2c-2为核心板内部电源管理使用),如下所示,其中i2c-1为通用I2C接口;i2c-0为DDC接口,用于连接HDMI DDC/EDID接口,不能用做通用I2C接口;而i2c-3通常用于连接camera接口使用,不过也可以用做通用I2C接口。
b). 本文演示示例则通过读写ApalisIxora载板连接在i2c-1总线上面的2Kb EEPROM
c). User Space下通过I2C tools直接操作i2c-1总线进行访问EEPROM
./ 查看Apalis iMX6Q的所有I2C总线
---------------------------------
root@apalis-imx6:~# ls -l /dev/i2c-*
crw------- 1 root root 89, 0 4??月 26 06:52 /dev/i2c-0
crw------- 1 root root 89, 1 4??月 26 06:52 /dev/i2c-1
crw------- 1 root root 89, 2 4??月 26 06:52 /dev/i2c-2
crw------- 1 root root 89, 3 4??月 26 06:52 /dev/i2c-3
--------------------------------
./ 查看i2c-1总线上面的设备
可以看到在0x50和0x68两个地址上面挂有设备,0x68显示为UU意味着这个设备被kernel driver占用,通常不能从user space探查,这里结合Apalis iMX6Q手册可以得知挂载的为外部RTC设备;而0x50则为我们所需要测试的EEPROM设备
--------------------------------
--------------------------------
./ dump 0x50 EEPROM全部寄存器地址0-0xff,初始状态下每个寄存器地址保存的数值都是0xff
--------------------------------
--------------------------------
./使用i2cset和i2cget来写和读EEPROM特定寄存器地址
--------------------------------
// 向EEPROM 0x00寄存器地址写入0x01
root@apalis-imx6:/home# i2cset 1 0x50 0x000x01 b
WARNING! This program can confuse your I2Cbus, cause data loss and worse!
DANGEROUS! Writing to a serial EEPROM on amemory DIMM
may render your memory USELESS and makeyour system UNBOOTABLE!
I will write to device file /dev/i2c-1,chip address 0x50, data address
0x00, data 0x01, mode byte.
Continue? [y/N] y
// 读取EEPROM 0x00寄存器地址
root@apalis-imx6:/home# i2cget 1 0x50 0x00b
……
0x01
--------------------------------
d). User Space下通过I2C tools读取i2c-1总线进行访问RTC芯片
./Apalis Ixora载板外部RTC芯片使用ST m41t00 芯片,其内部集成8 byte寄存器用于存储时间相关信息,格式如下:
--------------------------------
1st byte: seconds register
2nd byte: minutes register
3rd byte: century/hours register
4th byte: day register
5th byte: date register
6th byte: month register
7th byte: years register
8th byte: control register
--------------------------------
./ Linux下查看当前时间
--------------------------------
root@apalis-imx6:~# date
2017??年 04??月 26??日 ??星??期??三 08:57:23 UTC
--------------------------------
./ Linux下手动修改当前时间,默认当设备联网时候自动联网校准时间是打开的
--------------------------------
// 关闭网络时间同步
timedatectl set-ntp 0
//手动设置时间并重启
timedatectl set-time 22:50:11
reboot
--------------------------------
./ 利用i2cget –f命令查看RTC寄存器数值示例
--------------------------------
// 查看当前系统时间设置
root@apalis-imx6:~# date
2017??年 04??月 26??日 ??星??期??三 09:02:17 UTC
// 读取时数值
root@apalis-imx6:~# i2cget -f 1 0x68 0x02 b
……
0x09
// 读取分数值
root@apalis-imx6:~# i2cget -f 1 0x68 0x01 b
……
0x02
// 读取秒数值
root@apalis-imx6:~# i2cget -f 1 0x68 0x00 b
……
0x41
--------------------------------
4). I2C总线C程序操作示例
使用C程序打开I2C设备并进行读写,这里编写例程以访问i2c-1总线上的EEPROM设备进行读写操作。
a). 首先以C程序访问i2C设备,需要include “i2c-dev.h”这个头文件,请注意在Linux中有两个同样名字的头文件,系统自带的通常是来自Linux kernel的i2c总线驱动对应的,这个并不是我们所需要的,而我们所需的是i2c-tools里面提供的这个“i2c-dev.h”头文件,这个文件请见这里:
b). 示例C程序代码请参考这里,说明如下:
./ 首先程序含有输入变量,i2c总线号码,设备地址以及变量X,用于设置需要读写的寄存器地址:0xX0 – 0xXf
./ 使用open函数打开i2c总线
./ 使用ioctl函数设置设备地址
./ 利用 SMBus 命令或者write函数向寄存器地址 0xX0 – 0xXf写入数据,数值就是对应的寄存器地址
./ 利用SMBus命令或者read函数读取寄存器地址 0xX0 – 0xXf数据并打印出来
./ 关闭i2c总线设备并退出程序
c). 程序运行结果
--------------------------------
// 写入并读出寄存器0x00 – 0x0f
root@apalis-imx6:~# ./i2ctest 1 80 0
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x070x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x070x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
// 写入并读出寄存器0x10 – 0x1f
root@apalis-imx6:~# ./i2ctest 1 80 1
0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x170x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f
0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x170x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f
--------------------------------
这时dump EEPROM所有寄存器结果如下
--------------------------------
--------------------------------
d). 更多关于利用C程序使用I2C的说明请参考这里的内核文档说明。

提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 测试 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 计算机模块
Verdin iMX8MP 调试串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 测试