RTC子系统内核文档

来源:互联网 发布:如何看待网络水军 编辑:程序博客网 时间:2024/05/18 02:48

============================================
译者:yuanlulu
http://blog.csdn.net/yuanlulu


版权没有,但是转载请保留此段声明
============================================


RTC内核文档 英文原文地址:http://lxr.linux.no/linux+v2.6.38/Documentation/rtc.txt
用户空间使用RTC的例程在:http://lxr.linux.no/linux+v2.6.38/Documentation/rtc.txt#L216
Real Time Clock (RTC) Drivers for Linux
=======================================
Linux有两个基本兼容的用户空间RTC API家族:
     */dev/rtc 这是PC系统提供的兼容接口,不适用于非x86的系统
     */dev/rtc0 /dev/rtc1   这是大部分系统支持的形式。
虽然所有的RTC适用同样的API和RTC架构交互,但是硬件提供的功能并不一样。
比如不是所有的RTC都产生中断,所以它们不能做闹钟定时。
(在fedora 上/dev/rtc是一个指向/dev/rtc0的链接)

老式PC/AT兼容驱动:/dev/rtc
----------------------------------------
     /dev/rtc(主设备号10,次设备号135,只读字符设备)的中断以unsigned int的格式报告。最低的两字节包含中断类型(update-done, alarm-rang, or periodic),
剩下的字节包含自上次读取以来中断的次数。如果使能了proc文件系统,在/proc/driver/rtc下能读到中断的状态信息。由于驱动占有了锁,所以同一时间只能有
     一个进程占有/dev/rtc。
     用户进程可以使用read(2)或者select(2)监视/dev/rtc-它们都将阻塞在设备节点上直到下一个中断的到来。
     只有root用户能在dev/rtc上使用大于64HZ的中断。这个值可以通过往/proc/sys/dev/rtc/max-user/freq写入新的值来改变。记住中断处理函数应该尽可能简短。
     内核使用额外的代码来和RTC进行同步-内核每11分钟就将自己的时间写回CMOS。在回写的时候内核会关闭RTC的周期中断,
     所以依赖RTC周期中断的重要工作需要特别注意这一点。如果你的内核不和RTC进行同步,内核不会访问RTC,你可以把RTC做其它的用处。
     中断的频率是通过ioctl(2)调用/include/linux/rtc.h中的命令来设置的。

新式的“RTC class”接口:/dev/rtcN
----------------------------------------------
     由于linux支持的一些非ACPI和非PC平台有不止一个RTC,所以需要更具有可移植性的解决方案。
一种新的“RTC类”框架就是为此而生的,它支持三类用户空间接口:
     */dev/rtcN                和老式的/dev/rtc接口大体相同。
     */sys/class/rtc/rtcN     sysfs支持只读的访问RTC属性。
     */proc/driver/rtc             第一个RTC(rtc0)可以从procfs中暴露自己的更多信息(比sysfs多)。
    新的RTC class框架支持多种RTC,包括片上RTC和使用i2c、spi等接口的独立芯片。甚至支持在最新
的PC上通过ACPI暴露的特性。
     新的框架不再受"每个系统一个RTC”的约束。比如系统中可以有一个电池供电的低功耗i2c RTC芯片
和一个高性能的片上RTC。系统可以从外置的RTC读取时间,其它的任务或许需要从高性能的片内RTC。

SYSFS 接口
------
     sysfs接口在/sys/class/rtc/rtcN 下,可以直接访问。所有的数据和时间都是RTC的时区决定的,
而不是系统时间的时区
     
     date:                         日期:年月日
     hctosys:                    1:RTC在系统启动的时候通过CONFIG_RTC_HCTOSYS设置系统时间
                                        0:其它
     max_user_freq:         一般用户(不是root)能从RTC申请的最大中断速率。
     name:                         映射到这个目录的RTC的名字
     since_epoch:          和c函数time返回的值意义是一样的。
     time:                         时分秒。
     wakearm:               下一次系统唤醒事件的时间点。这个唤醒事件是一次性的,所以要多次唤醒的话需要在每次
                                        唤醒后重新设置。格式是下次唤醒的    since_epoch值,或者在开头有一个“+”号的话,表示
                                        未来多少秒后发生唤醒事件。

IOCTL接口
--------------
/dev/rtc支持的ioctl()接口同样支持新的RTC框架。
          * RTC_RD_TIME, RTC_SET_TIME      读取和设置时间。传递时间的参数是struct rtc_time结构体。
          * RTC_AIE_ON, RTC_AIE_OFF, RTC_ALM_SET, RTC_ALM_READ    alarm中断的开启、关闭、设置、读取。
               如果RTC和某个中断线相连,它可以在未来24小时内的某个时间段内产生中断。
               (建议优先使用RTC_WKALM_*
          * RTC_WKALM_SET, RTC_WKALM_RD     设置和读取 wakeup alarm触发的时间点。wakeup alarm和alrm
               中断唯一不同的是wakeup alrm可以申请超过24小时的定时中断。
          * RTC_UIE_ON, RTC_UIE_OFF     更新中断,每秒钟触发一次(更新的时候触发,因此每秒一次)。
          * RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ      周期中断的开启、关闭、设置、读取。
                      周期中断的频率必须是2^N(N>= 1),大于64的频率只有root用户才能设置。
          RTC_AIE_ON, RTC_AIE_OFF可以开启和关闭alarm和wake alarm的功能

yuanlulu的补充:
       * RTC_RD_TIME, RTC_SET_TIME的参数是一个struct rtc_time的指针。它的各个成员的含义和struct tm是一样的。
                    struct rtc_time {

                    int tm_sec;
                    int tm_min;
                    int tm_hour;
                    int tm_mday;
                    int tm_mon;
                    int tm_year;
                    int tm_wday;
                    int tm_yday;

                    int tm_isdst;
               };      

           * RTC_WKALM_SET, RTC_WKALM_RD wakeup_alarm和alarm中断的实现方式是一样的,参数structrtc_wkalrm指针
                    只是wake_alarm没有时间限制,可以指定未来任意时刻发生中断。
                                        struct rtc_wkalrm {
                                        unsigned char enabled;     /* 0 = alarm disabled, 1 = alarm enabled */
                                        unsigned char pending;  /* 0 = alarm not pending, 1 = alarm pending */
                                        struct rtc_time time;     /* time the alarm is set to */
                                   };
              * RTC_ALM_SET, RTC_ALM_READ 的传递参数也是struct rtc_time的指针,但只有时分秒的部分有效。时分秒
               这三个成员代表24小时以内的时间点。比如当前时间是13:00:00,而传入的参数是14:00:00,则意味着定时中断
               将在一小时后发生。而如果传入的参数是12:00:00,则意味着明天中午发生中断。总之,alarm 中断不能超过
               24小时。
                              
              *RTC_IRQP_SET, RTC_IRQP_READ 周期中断的参数是中断频率,参数必须是2^N(N>=1),也就是说
                         设置的周期中断必须大于2。并且只有root用户可以设置64HZ以上的频率。
     
RTC的中断方式有三类:
     1.更新中断,也就是RTC的时间更新的时候触发的中断。RTC每秒钟更新一次,所以更新中断的频率就是1。
     2.周期中断。频率可以设置为2^N(N>=1)。注意周期中断频率不可设置为1,否则会被忽略。
      3. alarm/wake alarm。这两个中断内部实现是一样的,只不过前者只能指定24小时内的某一时刻触发中断,后者没有限制。
 中断被触发后,可以从RTC设备节点中读取到一个unsigned long数据,最低两比特表示中断的类型。各bit的定义如下:
/* interrupt flags */
#define RTC_IRQF 0x80 /* any of the following is active */
#define RTC_PF 0x40          //周期中断
#define RTC_AF 0x20          //定时中断(alarm和wakeup alarm中断)
#define RTC_UF 0x10          //更新中断


再说RTC中断:RTC的中断概念和内核中的中断不是一回事,没有中断回调函数。但是在设备节点上使用select和read
          睡眠的函数会被唤醒,这就是RTC中断的功能。

另外RTC的设备节点,同一时刻只允许一个用户打开。不可能两个用户同时打开同一个RTC设备设备节点

经过测试,有以下结论:
     1.更新中断(1HZ)和周期中断可以同时开启。
     2.周期中断可以和alarm中断同时开启。
     3.alarm中断不可以和wakeup alarm中断同时开启,因为他们两个在内核中就是一回事。
     4..RTC_WKALM_SET不必设置struct rtc_wkalrm的enabled成员,只在读取的时候才需要这个成员。 
猜测:更新中断和可以和alarm中断同时开启。
          
 从RTC设备节点读取到的数据,包含了上次读取以来发生中断的次数(包括所有类型的中断)。
低字节会置位发生的所有中断类型。