1.eeprom 简介
EEPROM是一种掉电后数据不丢失的存储器,常用来存储一些配置信息,以便系统重新上电的时候加载之。EEPOM芯片最常用的通讯方式就是I2C协议.
I2C 是一个通信协议,它拥有严密的通信时序逻辑要求,而 EEPROM 是一个器件,只是这个器件采样了I2C 协议的接口与单片机相连而已,二者并没有必然的联系, EEPROM 可以用其他接口,I2C 也可以用在其它很多器件上。
EEPROM芯片(型号:HE24C128TSH)的SCL及SDA引脚连接到了SA226对应的I2C引脚中,构成了I2C通讯总线,它们通过I2C总线交互。EEPROM芯片的设备地址一共有7位,其中高4位固定为:1010b,低3位则由A0/A1/A2信号线的电平决定,见图EEPROM设备地址,图中的R/W是读写方向位,与地址无关。
A0/A1/A2均为0,所以EEPROM的7位设备地址是:1010000b,即0x50。由于I2C通讯时常常是地址跟读写方向连在一起构成一个8位数,且当R/W位为0时,表示写方向,所以加上7位地址,其值为“0xA0”,常称该值为I2C设备的“写地址”;当R/W位为1时,表示读方向,加上7位地址,其值为“0xA1”,常称该值为“读地址”。EEPROM芯片中还有一个WP引脚,具有写保护功能,当该引脚电平为高时,禁止写入数据,当引脚为低电平时,可写入数据,我们直接接地,不使用写保护功能。
2.dts配置
(1)dts配置
clock-frequency = <100000>;
he24c128: he24c128@0x50 {
compatible = "atmel,24c128";
reg = <0x50>;
status = "okay";
};
(2)使能配置
Device Drivers > Misc devices > EEPROM support > "I2C EEPROMs / RAMs / ROMs from most vendors"
|(3)读写函数
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
(4)设备驱动源码放在drivers/misc/eeprom/at24.c
# cd /sys/bus/i2c/drivers
# ls
at24 panel-lombo-simple-i2c
dummy goodix-ts
验证流程:
cd /sys/bus/i2c/drivers/at24/2-0050
/sys/devices/platform/4001000.i2c/i2c-2/2-0050 # echo "abcdefg12345" > eeprom
/sys/devices/platform/4001000.i2c/i2c-2/2-0050 # cat eeprom
abcdefg12345
3.测试程序流程:
测试代码:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/io.h>
#define EEPROM_DEV "/sys/bus/i2c/drivers/at24/2-0050/eeprom"
#define BUF_SIZE 256
int main(int argc, char **argv)
{
int ret, fd, i;
int j = 1,m=10;
char read_data[BUF_SIZE];
char write_data1[BUF_SIZE];
char write_data2[BUF_SIZE];
char *write_data;
fd = open(EEPROM_DEV, O_RDWR);
if(fd < 0){
printf("Open %s fail\n", EEPROM_DEV);
return -1;
}
for(i = 0; i < BUF_SIZE; i++){
write_data1[i] = 0x55 + i;
write_data2[i] = 0xAA + i * 2;
}
while(m--){
printf("\r\n######eeprom test start %d\r\n", j);
if(j % 2){
write_data = write_data1;
}else{
write_data = write_data2;
}
lseek(fd, 0 , SEEK_SET);
ret = write(fd, write_data, BUF_SIZE);
if(ret < 0){
printf("Write error\n");
return -1;
}
lseek(fd, 0 , SEEK_SET);
memset(read_data, 0x00, sizeof(read_data));
ret = read(fd, read_data, BUF_SIZE);
if(ret < 0){
printf("Read error\n");
return -1;
}
for(i = 0; i < BUF_SIZE; i++){
if(read_data[i] != *write_data++){
printf("Read/write inconsistency! offset=%d, read=0x%x, write=0x%x\n", i, read_data[i], *write_data);
break;
}
if(i % 16 == 0)
printf("\n");
printf(" 0x%02x ", read_data[i]);
}
if(i == BUF_SIZE){
printf("######eeprom test end PASS %d\r\n", j);
}else{
printf("######eeprom test end FAIL %d\r\n", j);
}
j++;
}
}
eeprom-test.c文件放到合适的地方
arm-linux-gnueabihf-gcc eeprom-test.c //生成a.out文件,更改为b名字后,scp到本地
adb push b /data //把b推送到开发板上,在cmd里面推
chmod +x b //给文件b获取权限 ,在串口/data下运行,adb shell 也行
./b // 运行点b文件