linux I2C之RTC8025、fm24cl16
来源:互联网 发布:软件工程推荐书籍知乎 编辑:程序博客网 时间:2024/06/06 13:19
说明:
主设备I2C-0挂载两个从设备fm24cl16铁电和RTC-rx8025t。
内核:linux3.10.32
平台:nuc972
1、板级文件修改 arch/arm/much-nuc970/dev.c
1.1 i2c-0的platform_device平台设备注册
//i2c-0的总线配置static struct nuc970_platform_i2c nuc970_i2c0_data = {.bus_num = 0,//这个参数很重要,决定i2c-0的总线为0,从设备通过0总线挂载到i2c-0适//配器上,下面会提到从设备通过i2c_register_board_info()注册设备信息,//其中该函数的第一个参数即为总线号,这样就将从设备与相应的i2c-0适配//器连接上,从设备就可以使用该适配器的资源,对外挂I2C硬件设备进行操作。.bus_freq = 100000,};//i2c-0的资源配置static struct resource nuc970_i2c0_resource[] = {[0] = {.start = NUC970_PA_I2C0,.end = NUC970_PA_I2C0 + NUC970_SZ_I2C0 - 1,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_I2C0,.end = IRQ_I2C0,.flags = IORESOURCE_IRQ,}};//platform_device平台设备资源struct platform_device nuc970_device_i2c0 = {.name = "nuc970-i2c0",.id = -1,.num_resources = ARRAY_SIZE(nuc970_i2c0_resource),.resource = nuc970_i2c0_resource,.dev = {.platform_data = &nuc970_i2c0_data,}};static struct platform_device *nuc970_public_dev[] __initdata = {&nuc970_device_i2c0,}//注册platform_device设备platform_add_devices(nuc970_public_dev, ARRAY_SIZE(nuc970_public_dev));
1.2 注册i2c从设备信息
<span style="white-space:pre"></span>//i2c-0下的从设备设备信息static struct i2c_board_info __initdata nuc970_i2c_clients0[] = {{I2C_BOARD_INFO("fm24cl16bg", 0x50),},//由于I2C发送数据时,首现发送的第一个字节是对外围从设备进行寻址,我们知道首字节的//高4bit(bit7~4)是外围设备的厂商编码,bit3~1是外围设备的地址(具体地址由该芯片的//外围电路决定),而bit0是对表示当前'读/写'操作,这里的0x50没有包括bit0‘读写’操作,<span style="white-space:pre"></span>//所以这里的0x50只有7个bit,适配器在进行操作时会左移一位,0x50=01010000b -> 向左偏<span style="white-space:pre"></span>//移1bit=1010 000x,高bit7~4为A恰好是fm24cl16的厂商编码,bit3~1为0恰好是外围器件地址。{I2C_BOARD_INFO("rx8025", 0x32),},//同上。};//注册i2c从设备信息i2c_register_board_info(0, //这里有必要说明下,0就是1.1中提到的bus_num的总线,通过该总线就将从设备与nuc970-i2c0适配器进行了连接nuc970_i2c_clients0, sizeof(nuc970_i2c_clients0)/sizeof(struct i2c_board_info));
2 platform_driver设备驱动注册 drivers/i2c/busses/i2c-nuc970-p0.c
2.1 平台设备驱动注册
//平台设备驱动static struct platform_driver nuc970_i2c0_driver = {.probe= nuc970_i2c0_probe,//具体操作见各arm厂家.remove= nuc970_i2c0_remove,.driver= {.name= "nuc970-i2c0",.owner= THIS_MODULE,},};//注册平台设备驱动,当结构体nuc970_i2c0_driver与nuc970_device_i2c0中名字相同时将用//函数nuc970_i2c0_probe,该函数将完成具体的gpio、中断资源、及适配器和从设备的初始化。//module_platform_driver=platform_driver_register()+platform_driver_unregister()可//以省去人为对资源的释放module_platform_driver(nuc970_i2c0_driver);
3 RTC 设备驱动
3.1 RTC设备驱动注册
static const struct i2c_device_id rx8025_id[] = {{ "rx8025", 0 },{ }};MODULE_DEVICE_TABLE(i2c, rx8025_id);static struct i2c_driver rx8025_driver = {.driver = {.name = "rtc-rx8025",.owner = THIS_MODULE,},.probe= rx8025_probe,.remove= rx8025_remove,.id_table= rx8025_id,//这里注册的设备名很重要,一定要与1.2中的名字相同,否则在执行//module_i2c_driver()时将不能调用rx8025_probe函数。};//同上2.1的分析是一样的module_i2c_driver(rx8025_driver);
3.2 内核配置单配置
为了系统一上电就同步硬件RTC时钟,需修改配置单:Device Drivers ---> <*> I2C support ---> --- I2C support [*] Enable compatibility bits for old user-space < > I2C device interface < > I2C bus multiplexing support [*] Autoselect pertinent helper modules I2C Hardware Bus support ---><*> GPIO-based bitbanging I2C <*> NUC970 I2C Driver for Port 0 [*] Real Time Clock ---> [*] Set system time from RTC on startup and resume [*] Set the RTC time based on NTP synchronization (rtc0) RTC used to set the system time [*] RTC debug support *** RTC interfaces *** [*] /sys/class/rtc/rtcN (sysfs) [*] /proc/driver/rtc (procfs for rtcN) [*] /dev/rtcN (character devices) [ ] RTC UIE emulation on dev interface <*> Epson RX-8025SA/NB3.3 编译、烧录内核
终端在上电之后会同步时间,并生成相应的设备/dev/rtc0, 通过date -s "2016-05-02 22:59:00", hwclock -w 将时间写到RTC时钟,
再次重启之后终端时间为之前设置的。
4 fm24cl16驱动
之前使用内核自带的设备驱动程序 i2c-dev.c,其中自己增加了lseek函数实现对外挂铁电设备进行指定地址读写,由于存在风险,还是直
接用at24.c代码进行小部分修改。
4.1 fm24cl16设备驱动程序注册
static const struct i2c_device_id at24_ids[] = {{ "fm24cl16bg", AT24_DEVICE_MAGIC(16384 / 8, 0) },//FM24CL16add by CL};MODULE_DEVICE_TABLE(i2c, at24_ids);static struct i2c_driver at24_driver = {.driver = {.name = "at24",//这个参数不重要,随便定义都可以.owner = THIS_MODULE,},.probe = at24_probe,.remove = at24_remove,.id_table = at24_ids,//id表里的名称一定要与1.2中的名字相同,否则无法执行at24_probe};//驱动程序注册static int __init at24_init(void){if (!io_limit) {<span style="white-space:pre"></span>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);}module_init(at24_init);//驱动程序释放static void __exit at24_exit(void){i2c_del_driver(&at24_driver);}module_exit(at24_exit);MODULE_DESCRIPTION("Driver for most I2C fm24cl16");MODULE_AUTHOR("ZDH-CL");MODULE_LICENSE("GPL");4.2 应用程序测试
由于使用4.1中的方式没有在/dev目录下生成相应的设备,在对设备进行open\read\write操作,需使用该路径/sys/bus/i2c/devices/0-0050/fram,其中fram是我修改了at24.c的源码
//at24->bin.attr.name = "eeprom";
at24->bin.attr.name = "fram";
open("/sys/bus/i2c/devices/0-0050/fram", O_RDWR);
....
0 0
- linux I2C之RTC8025、fm24cl16
- Linux设备之I2C
- Linux驱动之i2c
- Linux设备之I2C
- linux之I2C驱动程序
- linux I2C 驱动之---- i2c 编程接口
- Linux之I2C设备总结
- Linux驱动子系统之I2C
- linux i2c 驱动之二
- linux设备驱动之I2C
- Linux驱动子系统之I2C
- linux之i2c设备注册
- linux驱动之--I2C子系统
- Linux设备之I2C体系
- Linux驱动之I2C总线
- Linux Kernel 设备驱动之I2C之i2c设备文件
- Linux内核驱动之i2c子系统(一)i2c协议
- linux I2C 驱动之----i2c驱动的注册过程
- BestCoder Round #82 (div.2) A B
- Public and Private Interfaces in ruby
- Windows无法访问VMWare虚拟机下CentOS的apache服务器
- 微软研发类实习生面试
- GBDT理解二三事
- linux I2C之RTC8025、fm24cl16
- java中对类的方法的进行加强(1)--对类方法的覆盖
- 求二叉树中和为给定值的路径
- springMVC(10)------重定向处理
- mysql读写分离
- 单链表的基本操作
- C语言学习笔记
- 六、树和二叉树--(2)二叉树的先序遍历、中序遍历、后序遍历
- 删除排序链表中的重复数字 II