系统开机时一般会通过/dev/rtc设备来获取当时时间,所以肯定有一个驱动用于支持这个/dev/rtc设备的。在内核的drivers/char中找到了ds1302.c的驱动。在这个驱动中就注册了字符型设备。并支持RTC设备的ioctl(),RTC_RD_TIME和RTC_SET_TIME这2个最为重要的控制方法。
先看一下这个模块注册函数:
module_init(ds1302_register);
再往下找,下面调用了register_chrdev()注册字符设备接口,将主设备号,设备名称和函数操作指针绑定在了一起。
staticint__init ds1302_register(void)
{
ds1302_init();
if(register_chrdev(RTC_MAJOR_NR, ds1302_name, &rtc_fops)) {
printk(KERN_INFO"%s:unable to get major %d for rtc\n",
ds1302_name, RTC_MAJOR_NR);
return-1;
}
return0;
}
int__init
ds1302_init(void)
{
if(!ds1302_probe())
{
return-1;
}
return0;
}
下面来看看probe()函数是干什么的,从字面意思是枚举设备。从英文上来看,是通过向它的RAM写入一个值再读回来判断读回来的跟写入的是否一样,一样就说明找到设备了。
/*Probe for the chip by writing something to its RAM and try reading itback. */
#defineMAGIC_PATTERN 0x42 这个就是特定的值。
staticint__init
ds1302_probe(void)
{
intretval, res, baur;
baur=(boot_cpu_data.bus_clock/(2*1000*1000));
printk("%s:Set PLD_RTCBAUR = %d\n",ds1302_name,baur);
outw(0x0000,(unsignedlong)PLD_RTCCR);
outw(0x0000,(unsignedlong)PLD_RTCRSTODT);
outw(baur,(unsignedlong)PLD_RTCBAUR);
/*Try to talk to timekeeper.*/
ds1302_wenable(); 这里是写使能吗?
/*write RAM byte 0 */
/*write something magic */
out_byte_rtc(0xc0,MAGIC_PATTERN); 往0xc0寄存器写个这个特定的值。
/*read RAM byte 0 */
if((res= in_byte_rtc(0xc1)) == MAGIC_PATTERN) {
charbuf[100];
ds1302_wdisable();写禁止。
printk("%s:RTC found.\n",ds1302_name);
get_rtc_status(buf);
printk(buf);
retval= 1; 读回来的跟写入的一模一样,所以枚举成功。
}else{
printk("%s:RTC not found.\n",ds1302_name);
retval= 0; 读回来的值有问题。
}
returnretval;
}
再来看看这个写使能,写关闭是什么意思,很简单,就是往0x8e寄存器,分别写入0x0和0x80,看来这个最高位,控制着是否可写。要往ds1302寄存器里写操作,必须将最高位清0呀。
/*Enable writing. */
staticvoid
ds1302_wenable(void)
{
out_byte_rtc(0x8e,0x00);
}
/*Disable writing. */
staticvoid
ds1302_wdisable(void)
{
out_byte_rtc(0x8e,0x80);
}
再来看看,底层的读写函数,看一样,数据是怎么被送到ds1302的。
先看写函数,从流程上来看,好像是遵守了一些时序,
1、先将RST拉高;
2、再写入8位数据;
3、再产生WE(WriteEnable)写使能信号
4、再等待。???等什么信号呢?
5、再将RST