RTC子系统内核文档

简介:

============================================
译者: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中断的实现方式是一样的,参数 struct rtc_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设备节点读取到的数据,包含了上次读取以来发生中断的次数(包括所有类型的中断)。
低字节会置位发生的所有中断类型。
目录
相关文章
|
5月前
|
存储 Linux 调度
【看表情包学Linux】系统下的文件操作 | 文件系统接口 | 系统调用与封装 | open,write,close 接口 | 系统传递标记位 O_RDWR,O_RDONLY,O_WRONLY...
【看表情包学Linux】系统下的文件操作 | 文件系统接口 | 系统调用与封装 | open,write,close 接口 | 系统传递标记位 O_RDWR,O_RDONLY,O_WRONLY...
40 1
|
4月前
|
存储 API 开发者
6.7 Windows驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。
32 1
6.7 Windows驱动开发:内核枚举LoadImage映像回调
|
4月前
|
存储 Windows
4.6 Windows驱动开发:内核遍历进程VAD结构体
在上一篇文章`《内核中实现Dump进程转储》`中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍`VAD`结构,该结构的全程是`Virtual Address Descriptor`即`虚拟地址描述符`,VAD是一个`AVL`自`平衡二叉树`,树的每一个节点代表一段虚拟地址空间。程序中的代码段,数据段,堆段都会各种占用一个或多个`VAD`节点,由一个`MMVAD`结构完整描述。
37 0
4.6 Windows驱动开发:内核遍历进程VAD结构体
|
Linux 编译器 SoC
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
195 0
内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
|
API
HarmonyOS系统内核中使用事件标志的方法
大家好,今天主要和大家聊一聊,如何利用HarmonyOS系统中事件标志。
215 0
HarmonyOS系统内核中使用事件标志的方法
|
监控
驱动开发:内核监控FileObject文件回调
本篇文章与上一篇文章`《驱动开发:内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShark`将回调结构体`OB_OPERATION_REGISTRATION`中的`ObjectType`填充为了`PsProcessType`和`PsThreadType`格式从而实现监控进程与线程,本章我们需要将该结构填充为`IoFileObjectType`以此来实现对文件的监控,文件过滤驱动不仅仅可以用来监控文件的打开,还可以用它实现对文件的保护,一旦驱动加载则文件是不可被删除和改动的。
318 0
驱动开发:内核监控FileObject文件回调
|
存储
驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《驱动开发:内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。
268 1
驱动开发:内核枚举LoadImage映像回调
|
监控 API
驱动开发:对象回调监控文件访问
无论在用户层还是内核层,操作文件的流程基本一致,除了在API函数上的区别(用户层调用用户层API,内核层调用内核API)以外其他基本一致,先讲解一下文件系统执行的流程。实现文件的监控呢,比如当文件被访问时自动触发回调,看如下代码实现方式。
198 0
|
监控
驱动开发:通过Async反向与内核通信
在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用`Async`异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒软件如果监控到有异常进程运行或有异常注册表被改写后,该驱动需要主动的通知应用层进程让其知道,这就需要用到驱动反向通信的相关知识点,如下将循序渐进的实现一个反向通信案例。
196 0
驱动开发:通过Async反向与内核通信
|
监控
驱动开发:内核监视LoadImage映像回调
在笔者上一篇文章`《驱动开发:内核注册并监控对象回调》`介绍了如何运用`ObRegisterCallbacks`注册`进程与线程`回调,并通过该回调实现了`拦截`指定进行运行的效果,本章`LyShark`将带大家继续探索一个新的回调注册函数,`PsSetLoadImageNotifyRoutine`常用于注册`LoadImage`映像监视,当有模块被系统加载时则可以第一时间获取到加载模块信息,需要注意的是该回调函数内无法进行拦截,如需要拦截则需写入返回指令这部分内容将在下一章进行讲解,本章将主要实现对模块的监视功能。
307 0
驱动开发:内核监视LoadImage映像回调