IIC專題(二)-使用核心原始碼提供的at24.c驅動來操作I2C的at24lc04 EEPROM
阿新 • • 發佈:2018-12-22
前面第一篇已經講了有關IIC的相關知識這邊就不再重複,
本篇我們使用核心原始碼提供的at24.c驅動來操作I2C的at24lc04 EEPROM
核心I2C子系統的架構請參考第一篇文章,這邊只講at24.c相關的部份
接下來因為驅動使用的是核心 at24.c 檔案當然得先分析一下該檔案
首先看到的是ar24.c驅動支援的裝置
static const struct i2c_device_id at24_ids[] = { /* needs 8 addresses as A0-A2 are ignored */ { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, /* old variants can't be handled with this generic entry! */ { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, /* spd is a 24c02 in memory DIMMs */ { "spd", AT24_DEVICE_MAGIC(2048 / 8, AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, /* 24rf08 quirk is handled at i2c-core */ { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, { "at24", 0 }, { /* END OF LIST */ } };
我們24c04是在列表中的,總共有4096位/8 = 512位元組
在初始化驅動時有這樣的程式碼片段
static struct i2c_driver at24_driver = { .driver = { .name = "at24", .owner = THIS_MODULE, }, .probe = at24_probe, .remove = __devexit_p(at24_remove), .id_table = at24_ids, }; static int __init at24_init(void) { if (!io_limit) { pr_err("at24: io_limit must not be 0!\n"); return -EINVAL; } io_limit = rounddown_pow_of_two(io_limit); return i2c_add_driver(&at24_driver); }
也就是說這是採用匯流排的驅動,匯流排的過程是當有裝置加入匯流排,會呼叫驅動的 probe 方法來捕獲裝置,
驅動已經實現了probe 方法剩下的是得把我們的裝置加入匯流排,尋找smart210的裝置加入匯流排的操作部分,
發現坑人的是明明是 smart210 應該是s5kv210的核心結果對應到的檔案居然是 Mach-mini210.c 而不是Mach-smdkv210.c
找到該檔案加入以下的程式碼
//add by yang
#include <linux/i2c.h>
#include <linux/i2c/at24.h>
以上是使用at24.c 的標頭檔案
這個是我們裝置的描述,因為at24.c是對應多種裝置的,所以需要加上板載的一些資訊,//add by yang static struct at24_platform_data at24c04 = { .byte_len = 4096 / 8, .page_size = 16, .flags = 0, }; static struct i2c_board_info __initdata smdkv210_i2c_devices[] = { { I2C_BOARD_INFO("24c04", 0x50), .platform_data = &at24c04, }, };
然後找到mini210_machine_init 這個函式將上面的裝置資訊加入匯流排
static void __init mini210_machine_init(void)
{
arm_pm_restart = smdkc110_pm_restart;
.....這邊省略一堆程式碼.....
#ifdef CONFIG_TOUCHSCREEN_GOODIX
if (mini210_get_ctp() == CTP_GT80X) {
i2c2_data.frequency = 260*1000;
}
#endif
//add by yang
i2c_register_board_info(0, smdkv210_i2c_devices,ARRAY_SIZE(smdkv210_i2c_devices));
s3c_i2c2_set_platdata(&i2c2_data);
i2c_register_board_info(0, mini210_i2c_devs0,
ARRAY_SIZE(mini210_i2c_devs0));
i2c_register_board_info(1, mini210_i2c_devs1,
ARRAY_SIZE(mini210_i2c_devs1));
i2c_register_board_info(2, mini210_i2c_devs2,
ARRAY_SIZE(mini210_i2c_devs2));
....下面省略一堆程式碼.......
主要將剛剛定義好的裝置描述加入匯流排
最後檢查一下核心中的EEPROM支援是否已經開啟
核心中的eeprom沒開啟,請先到核心配置以下選項
Device Drivers --->
[*] Misc devices --->
EEPROM support --->
<*>I2C EEPROMs from most vendors重新編譯下載核心之後可以發現在 /sys/bus/i2c/devices/0-0050/ 目錄下應該要有 eeprom 裝置檔案
這樣就算準備就緒
最後實現應用程式程式碼如下/***********************************************
* 檔名:i2c_app.c
* 作者:[email protected]
* 日期:2016/10/13
* 描述:使用Linux核心提供的at24.c驅動讀寫板載AT24C04
************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <unistd.h>
int main()
{
int fd;
int i;
char write_data[8] = {
0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40
};
char read_data[256] = {0};
fd = open("/sys/bus/i2c/devices/0-0050/eeprom",O_RDWR);
for(i=0;i<8;i++)
write_data[i] = i;
//使用lseek來定位資料地址
lseek(fd,0,SEEK_SET);
write(fd,write_data,8);
lseek(fd,0,SEEK_SET);
read(fd,read_data,256);
for(i=0;i<256;i++)
{
if(i%16 == 0)
printf("\n");
printf("%02x ",read_data[i]);
}
printf("\n");
}