rtc驱动模型及rx8025驱动学习

rtc驱动模型及rx8025驱动学习
一、芯片简单了解
RX8025-T是一款 拥有I2C接口和温度补偿功能的新型实时时钟芯片 ,内部集成32.768KHz温度补偿晶体振荡器,可用于各种需要高精度时钟的场合。通过设置相应补偿的控制位,可以实现不同间隔的温度补偿功能,从而大大提高了时钟的精度。芯片可设置四种不同的时段进行温度补偿,默认设置是2S补偿。该芯片采用C-MOS工艺生产,具有极低的功能消耗,可长期使用电池供电。
 
芯片特点:
1.内置高稳定度的32.768KHz 的DTCXO (数字温度补偿晶体振荡器)
2. 支持I2C 总线的高速模式(400K)
3. 定时报警功能(可设定:天,日期,小时,分钟)
4. 固定周期定时中断功能。
5. 时间更新中断功能。
6. 32.768KHz频率输出(具有使能OE功能)
7. 闰年自动调整功能。(2000 到2099)
8. 宽范围接口电压:2.2V 到 5.5V
9. 宽范围的时间保持电压:1.8V 到 5.5V
10. 低电流功耗:0.8uA/3V (Typ.)
11. 工作温度:-45℃~85℃
 
操作模式:
1)实时时钟模式
        该功能被用来设定和读取年,月,日,星期,时,分,秒 时间信息。年份为后两位数字表示, 任何可以被4 整除的年份被当成闰年处理。(2000 年到2099 年)
2)固定周期的中断发生功能:
        固定周期定时中断发生功能可以产生一个固定周期的中断事件,固定周期可在244.14uS 到 4095 分钟之间的 任意时间设定。
3)  定时更新中断功能:
        该功能可以根据内部时钟的定时设定,每秒或每分钟产生一个中断事件。 当中断事件产生,UF 标志位的值变成 1 同时/INT 引脚变成低电平表示一个中断事件的产生。
4)闹钟中断功能:
        该功能可以根据报警设定来产生一个中断。
5)32.768K Hz 时钟输出:
        可以通过FOUT 引脚来输出一个32.768kHz 频率的时钟信号,该功能可以通过FOE 引脚控制。
6)和CPU 的接口功能:
        数据的读写都是通过I2C 总线接口的方式来完成。
 
二、开发板硬件相关
 
芯片设计原理图:
rtc驱动模型及rx8025驱动学习
 
与主控芯片连接关系:
rtc驱动模型及rx8025驱动学习
rtc驱动模型及rx8025驱动学习
rtc驱动模型及rx8025驱动学习
设备树中定义:
rtc驱动模型及rx8025驱动学习
 
三、RTC设备驱动模型学习
驱动模型结构
        与RTC核心有关的文件有:
        /drivers/rtc/class.c          这个文件向linux设备模型核心 注册了一个类RTC ,然后向驱动程序提供了注册/注销接口
        /drivers/rtc/rtc-dev.c       这个文件定义了基本的设备文件操作函数,如:open,read等
        /drivers/rtc/interface.c     顾名思义, 这个文件主要提供了用户程序与RTC驱动的接口函数,用户程序一般通过ioctl与RTC驱动交互,这里定义了每个ioctl命令需要调用的函数
        /drivers/rtc/rtc-sysfs.c     与sysfs有关
        /drivers/rtc/rtc-proc.c      与proc文件系统有关
        /include/linux/rtc.h         定义了与RTC有关的数据结构
        
        RTC驱动模型结构如下图:(可以看出对于rtc的开发就是对具体的芯片的驱动开发,与应用层交互的字符设备部分内核已经提供,只需建立起相应联系即可)
rtc驱动模型及rx8025驱动学习
内核提供的的基本数据结构:
 
1. struct rtc_device 结构
     这个结构是RTC驱动程序的基本数据结构,但是他不像其他核心的基本结构一样,驱动程序以他为参数调用注册函数注册到核心。这个结构是由注册函数返回给驱动程序的。
2. struct rtc_class_ops 结构
     这个结构是RTC驱动程序要实现的基本操作函数,注意这里的操作不是文件操作。驱动程序通过初始化这样一个结构,将自己实现的函数与RTC核心联系起来。这里面的大部分函数都要驱动程序来实现。而且这些函数都是操作底层硬件的,属于最底层的函数。
 
rtc驱动模型及rx8025驱动学习
3. struct rtc_time 结构
     代表了时间与日期,从RTC设备读回的时间和日期就保存在这个结构体中
 
4.注册: 为底层驱动提供接口: rtc_device_register,rtc_device_unregister
 
 
四、rx8025驱动分析
     
     首先在probe函数做了如下的工作:
rtc驱动模型及rx8025驱动学习
 
 
然后实现rx8025读写寄存器的函数,(这里提供了读连续地址的数据的操作函数)
rtc驱动模型及rx8025驱动学习
 
接下来就是填充struct rtc_class_ops结构体的函数:(具体就是对寄存器的操作)
rtc驱动模型及rx8025驱动学习
 
在rtc8025驱动中没有对于相关的字符驱动的函数,所以需要做进一步的分析:   
 
应用层调用关系解读:(具体的字符设备接口函数在rtc-dev.c中实现)
 
         在probe函数中 rtc_device_register()注册rtc时,中会调用rtc_dev_prepare(rtc)函数,    r tc_dev_prepare()函数rtc-dev.c中定义这就是对具体的字符设备的初始化,从而将 struct rtc_class_ops结构体的函数与struct file_operations rtc_dev_fops结构体中的函数建立起了联系。
 
当用户open时会调用 rtc_class_ops 中的open,open则会调用到rtc_class_ops中定义的open,如下:
rtc驱动模型及rx8025驱动学习
 
其中应用层使用核心的是ioctl函数,例如以下的指令调用:( 调用了 中的rtc_read_time和rtc_set_time函数
rtc驱动模型及rx8025驱动学习
 
阅读ioctl会发现每个指令都会调用/drivers/rtc/interface.c  中定义的函数,以RTC_RD_TIME命令的rtc_read_time()为例,继续追踪:
 
rtc驱动模型及rx8025驱动学习
 
调用了__rtc_read_time();
 
rtc驱动模型及rx8025驱动学习
如上图绿色框,最终是调用了rx8025中struct rtc_class_ops中定义实现的函数,即我们写的读时间函数。
 
所以 最终结论 就是:rtc驱动开发只需要去实现 struct rtc_class_ops结构体的函数即可,具体与应用层交互的字符驱动函数,linux内核在 rtc-dev.c中定义 已经提供,其会产生相应节点为rtc(x)。