天天看點

RTC子系統核心文檔

============================================

譯者: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裝置節點讀取到的資料,包含了上次讀取以來發生中斷的次數(包括所有類型的中斷)。

低位元組會置位發生的所有中斷類型。

繼續閱讀