============================================
譯者:yuanlulu
http://blog.csdn.net/yuanlulu
版權沒有,但是轉載請保留此段聲明
=======================================
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裝置節點讀取到的資料,包含了上次讀取以來發生中斷的次數(包括所有類型的中斷)。
低位元組會置位發生的所有中斷類型。