閱讀970 返回首頁    go 阿裏雲 go 技術社區[雲棲]


RTC子係統內核文檔

============================================
譯者:yuanlulu
https://blog.csdn.net/yuanlulu


版權沒有,但是轉載請保留此段聲明
============================================


RTC內核文檔 英文原文地址:https://lxr.linux.no/linux+v2.6.38/Documentation/rtc.txt
用戶空間使用RTC的例程在:https://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設備節點讀取到的數據,包含了上次讀取以來發生中斷的次數(包括所有類型的中斷)。
低字節會置位發生的所有中斷類型。

最後更新:2017-04-03 18:51:50

  上一篇:go linux下如何寫RTC驅動
  下一篇:go mac os X 下用nasm大雜燴