=======================================
Real Time Clock (RTC) Drivers for Linux
=======================================
当Linux开发人员谈论“实时时钟”时,他们通常指的是可跟踪墙上时钟时间并由电池供电的东西,以便即使在系统电源关闭的情况下也能正常工作。 此类时钟通常不会跟踪本地时区或夏时制时间(除非它们与MS-Windows双重启动),而是将其设置为协调世界时(UTC,以前称为“格林威治标准时间”)。
最新的非PC硬件往往只计数秒,如time(2)系统调用报告,但gmtime(3)报告,RTC也通常使用公历来表示时间和24小时制。
Linux有两个您可能需要了解的与用户空间基本兼容的RTC API系列:
* /dev/rtc ...是PC兼容系统提供的RTC,因此它对于非x86系统不是很容易移植。
* /dev/rtc0,/dev/rtc1 ...是框架的一部分,在所有系统上均受各种RTC芯片的支持。
程序员需要了解PC / AT功能并不总是可用,并且某些系统可以做更多的事情。 也就是说,RTC使用相同的API在两个RTC框架中发出请求(当然使用不同的文件名),但是硬件可能无法提供相同的功能。 例如,并不是每个RTC都挂接到一个IRQ,所以它们不能全部发出Alarm。 在将来标准PC RTC最多只能在24小时内发出Alarm的情况下,其他硬件可能能够在即将到来的世纪中的任何时间安排一个Alarm。
兼容旧PC / AT的驱动程序:/dev/rtc
--------------------------------------
所有PC(甚至包括Alpha机器)都内置有实时时钟。通常它们内置在计算机芯片组中,但有些可能实际上在板上装有Motorola MC146818(或克隆)。 当计算机关闭时,这是保留日期和时间的时钟。
ACPI已对该MC146818功能进行了标准化,并以几种方式对其进行了扩展(启用更长的警报时间以及从休眠状态唤醒)。 该功能未在旧驱动程序中公开。
但是,它也可以用于以2的幂为单位生成从慢2Hz到相对快的8192Hz的信号。这些信号由中断号8报告。(哦!所以*那是IRQ 8的意思。。。)它还可以用作24小时警报,在警报关闭时提高IRQ 8。还可以将警报编程为仅检查三个可编程值的任何子集,这意味着可以将其设置为例如每小时每小时30分钟的30秒响起。还可以将时钟设置为在每次时钟更新时生成一个中断,从而生成一个1Hz信号。
中断通过/dev/rtc(主要10,次要135,只读字符设备)以无符号long形式报告。低字节包含引发的中断类型(更新完成,警报范围或周期性),其余字节包含自上次读取以来的中断数量。如果启用了/proc文件系统,则通过伪文件/proc/driver/rtc报告状态信息。该驱动程序具有内置锁定功能,因此一次只允许一个进程打开/dev/rtc接口(但是实际测试不准)。
用户进程可以通过在/dev/rtc上执行read(2)或select(2)来监视这些中断-要么阻塞/停止用户进程,直到接收到下一个中断。 这对于诸如合理的高频数据采集(不想通过轮询gettimeofday等消耗100%的CPU等)之类的东西很有用。
在高频率或高负载下,用户进程应该检查自上次读取以来收到的中断数,以确定是否存在任何中断“堆积”。 仅供参考,对于频率高于1024Hz的典型486-33,在/dev/rtc上运行严格的读取循环将开始遭受偶尔的中断堆积(即自上次读取以来> 1个IRQ事件)。 因此,您确实应该检查所读取值的高字节,尤其是在高于正常计时器中断的频率(100Hz)的频率下。
只有root用户才能编程和/或启用大于64Hz的中断频率。 这也许有点保守,但是我们不希望邪恶的用户在较慢的386sx-16上生成大量的IRQ,这可能会对性能产生负面影响。 可以通过将不同的值写入 /proc/sys/dev/rtc/max-user-freq 来更改此64Hz限制。 请注意,中断处理程序仅是几行代码,以最大程度地减少这种影响的可能性。
同样,如果内核时间与外部源同步,则内核将每11分钟将时间写回CMOS时钟。 在此过程中,内核会暂时关闭RTC定期中断,因此,如果您正在认真工作,请注意这一点。 如果您不将内核时间与外部源(通过ntp或其他方式)同步,则内核将不使用RTC,从而使您可以独占访问应用程序的设备。
警报和/或中断频率通过 ./include/linux/rtc.h 中列出的各种ioctl(2)调用被编程到RTC中,而不是写50个描述ioctl()的页面,依此类推,它也许更有用 包括一个小型测试程序,该程序演示了如何使用它们并演示了驱动程序的功能。 对于有兴趣编写将使用此驱动程序的应用程序的人来说,这可能有用得多。 请参阅本文档末尾的代码。
(原始的/ dev / rtc驱动程序由Paul Gortmaker编写。)
新的便携式“ RTC类”驱动程序:/dev/rtcN
--------------------------------------------
因为Linux支持许多非ACPI和非PC平台,其中一些具有不止一个RTC风格的时钟,所以它需要一种比预期在每个系统上都有单个电池支持的MC146818克隆的便携式解决方案。 因此,已经定义了新的“ RTC类”框架。 它提供了三种不同的用户空间接口:
* /dev/rtcN ...与较早的/dev/rtc接口几乎相同
* /sys/class/rtc/rtcN ... sysfs属性支持只读访问一些RTC属性。
* /proc/driver/rtc ...系统时钟RTC可以使用procfs接口公开自身。 如果系统时钟没有RTC,则默认使用rtc0。 (当前)此处显示的信息比通过sysfs显示的信息更多。
RTC class 框架支持各种RTC,从集成到可嵌入的片上系统(SOC)处理器的RTC到使用I2C,SPI或其他总线与主机CPU进行通信的分立芯片。 甚至还支持PC样式的RTC,包括通过ACPI在较新PC上公开的功能。
新框架还消除了“每个系统一个RTC”的限制。 例如,低功耗电池支持的RTC可能是分立的I2C芯片,但是高性能RTC已集成到SOC中。 该系统可能从离散RTC读取系统时钟,但由于其功能更强大,因此可以将集成时钟用于其他所有任务。
SYSFS接口
---------------
/sys/class/rtc/rtcN 下的sysfs接口提供对各种rtc属性的访问,而无需使用ioctls。 所有日期和时间都在RTC的时区中,而不是系统时间中。
================ ==============================================================
date:RTC提供的日期
hctosys:如果RTC在启动时通过CONFIG_RTC_HCTOSYS内核选项提供了系统时间,则为1,否则为0
max_user_freq:非特权用户可以从此RTC请求的最大中断率。
name:与此sysfs目录相对应的RTC的名称
since_epoch:距RTC的纪元以来的秒数
time:RTC提供的时间
wakealarm:时钟将生成系统唤醒事件的时间。 这是一次触发的唤醒事件,因此如果需要每天唤醒,则必须在唤醒后将其重置。
格式默认为自该纪元以来的秒数,或者如果前导'+',则表示将来的秒数;如果存在前导'+=',则表示当前警报的秒数。
offset:已在固件中调整rtc时钟的数量。 仅在驱动程序支持时钟偏移调整时才可见。 单位是十亿分之几,即每十亿分之几添加到rtc基本时钟中或从中删除的时钟分时数。 正值使一天过得更慢,更长,而负值使一天过得更快。
*/nvmem:将非易失性存储作为原始文件导出,如Documentation/nvmem/nvmem.txt中所述.
注意:cat 时间显示的不准,没有 wakealarm 和 offset文件!!cat hctosys显示的是1的。
================ ==============================================================
IOCTL接口
---------------
RTC类框架也支持/dev/rtc支持的ioctl()调用。但是,由于芯片和系统尚未标准化,因此可能无法提供某些PC / AT功能。同样,RTC类框架公开了一些较新的功能(包括由ACPI启用的功能),但较旧的驱动程序不支持。
* RTC_RD_TIME,RTC_SET_TIME ...每个RTC至少支持阅读时间,并以公历日期和24小时挂钟时间返回结果。为了最有用,这个时间也可以被更新。
* RTC_AIE_ON,RTC_AIE_OFF,RTC_ALM_SET,RTC_ALM_READ ...当RTC连接到IRQ线路时,它通常会在未来24小时内发出警报IRQ。 (优先使用RTC_WKALM_ *。)
* RTC_WKALM_SET,RTC_WKALM_RD ...可以在未来24小时后发出警报的RTC使用功能稍强的API,该API支持设置较长的警报时间并使用单个请求启用其IRQ(使用与EFI固件相同的模型)。
* RTC_UIE_ON,RTC_UIE_OFF ...如果RTC提供IRQ,则RTC框架将模仿此机制。
* RTC_PIE_ON,RTC_PIE_OFF,RTC_IRQP_SET,RTC_IRQP_READ ...这些icotl是通过内核hrtimer进行仿真的。
在许多情况下,RTC警报可以是系统唤醒事件,用于迫使Linux从低功耗睡眠状态(或休眠状态)返回到完全运行状态。 例如,在执行某些计划任务之前,系统可能会进入深度节能状态。
请注意,许多这些ioctl由通用的rtc-dev接口处理。 一些常见的例子:
* RTC_RD_TIME,RTC_SET_TIME:将使用适当的值调用read_time / set_time函数。
* RTC_ALM_SET,RTC_ALM_READ,RTC_WKALM_SET,RTC_WKALM_RD:获取或设置警报rtc_timer。 可以调用set_alarm驱动程序函数。
* RTC_IRQP_SET,RTC_IRQP_READ:这些是由通用代码模拟的。
* RTC_PIE_ON,RTC_PIE_OFF:这些也由通用代码模拟。
如果所有其他方法均失败,请检出tools/testing/selftests/timers/rtctest.c测试!