9g10中pit(periodic interval timer)提供os排程中斷,它提供了最高精度和最有效的管理(即使系統長時間響應)。
一. 硬體
pit目標是提供os的週期中斷。pit提供乙個可程式設計溢位計數器和乙個reset-on-read特性。它包含兩個計數器:20bit cpiv counter和12bit picnt(periodic interval) counter。兩個計數器都工作在master clock/16。
cpiv從0增加到pit_mr中piv設定值,到達設定值後復位(0)且picnt加1。假如中斷是能,pit_sr的pits位置位,觸發乙個中斷。
寫乙個新的piv值到pitmr不會reset/restart計數器。
當讀取pit_pivr(periodic interval value register)時,picnt復位(0),且pits清零(獲取到乙個中斷)。picnt表示自從上次讀取pit_pivr後多少個periodic interval過去了。
當讀取pit_piir(periodic interval image register)時,對cpiv和picnt無影響。
pit可通過pit_mr的piten位使能或關閉,僅當cpiv變為0時piten才生效。
pit共有4個暫存器,分別是pit_mr(mode register),pit_sr(status register),pit_pivr(periodic interval value register),pit_piir(periodic interval image register)。
pit_mr: bit0-19 piv, bit24 piten, bit25 pitien
pit_sr:bit0 pits
pit_pivr:bit0-19 cpiv,bit20-31 picnt
pit_piir:bit0-19 cpiv,bit20-31 picnt
二. 軟體
在板級檔案中machine_desc中設定timer=&at91sam926x_timer,下面看下at91sam926x_timer的初始化函式。
at91sam926x_time.c
/** set up both clocksource and clockevent support.
*/static void __init at91sam926x_pit_init(void)
static struct clocksource pit_clk = ;
static struct clock_event_device pit_clkevt = ;
clocksource註冊過程
clocksource_register(&pit_clk); -->clocksource_enqueue(&pit_clk);
將pit_clk新增到系統時鐘源list中。
clockevents_register_device(&pit_clkevt);
-->clockevents_do_notify(clock_evt_notify_add, &pit_clkevt);
--> raw_notifier_call_chain(&clockevents_chain, reason, &pit_clkevt);
-->__raw_notifier_call_chain(nh, val, v, -1, null);
-->notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
-->nb->notifier_call(nb, val, v);
即nb->notifier_call((&clockevents_chain)->head, clock_evt_notify_add, &pit_clkevt);
kernel/notifier.c
notifier_call()函式的初始化在start_kernel()的tick_init()中,後面分析。
-->tick_check_new_device(&pit_clkevt); //kernel/time/tick-common.c
確認clock_event_device的rating是否高於當前的,高於則替換當前時鐘事件裝置
若pit_clkevt->features&clock_evt_feat_oneshot 還要呼叫 tick_oneshot_notify()
-->tick_setup_device(td, newdev, cpu, cpumask_of(cpu));
-->tick_setup_periodic(newdev, 0);
---->tick_set_periodic_handler(newdev, 0);
------>(&pit_clkevt)->event_handler = tick_handle_periodic;
// kernel/time/tick-common.c
即設定pit_clkevt的事件處理函式為tick_handle_periodic()。
---->clockevents_set_mode(dev, clock_evt_mode_periodic);
---->(&pit_clkevt)->set_mode(clock_evt_mode_periodic, &pit_clkevt);
pit_clkevt.mode = clock_evt_mode_periodic;
至此呼叫pit_clkevt的set_mode()函式,完成全部初始化工作
在init/main.c的start_kernel()中tick_init()呼叫過程:
tick_init(); //kernel/time/tick-common.c
-->clockevents_register_notifier(&tick_notifier);
-->raw_notifier_chain_register(&clockevents_chain, nb);
-->notifier_chain_register(&nh->head, n); // kernel/notifier.c
-->向clockevents_chian註冊tick_notifier()
static int tick_notify(struct notifier_block *nb, unsigned long reason,
void *dev)
return notify_ok;
}static struct notifier_block tick_notifier = ;
即向系統註冊了notifier_block結構體tick_notifier的notifier_call()**函式。
中斷處理過程
根據初始化過程,每個tick或hz產生一次中斷。
static struct irqaction at91sam926x_pit_irq = ;
static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
while (nr_ticks);
return irq_handled;
}return irq_none;
}at91sam926x_pit_interrupt()
-->pit_clkevt.event_handler(&pit_clkevt);
-->tick_handle_periodic(&pit_clkevt); //kernel/time/tick-common.c
-->tick_periodic(cpu);
-->do_timer(1); //kernel/timer.c 更新jiffies_64和時間
-->update_times(ticks);
-->update_wall_time(); //更新xtime
void do_timer(unsigned long ticks)
static inline void update_times(unsigned long ticks)
三. 知識擴充套件
1)時鐘系統中最重要的結構體變數:clockevent clocksource xtime。
clockevent為kernel提供了時鐘中斷的一些處理函式,特別是對於tickless系統,提供了設定下一次時鐘中斷時間點的介面set_next_event和timer模式設定介面set_mode。
clocksource則是kernel真正的計數者 時鐘源,常規的時鐘中斷中的計數以及提高精度的補充計數都來自於clocksource。
clocksource成員rating代表了時鐘精度,參考值如下:
1--99: 不適合於用作實際的時鐘源,只用於啟動過程或用於測試;
100--199:基本可用,可用作真實的時鐘源,但不推薦;
200--299:精度較好,可用作真實的時鐘源;
300--399:很好,精確的時鐘源;
400--499:理想的時鐘源,如有可能就必須選擇它作為時鐘源;
xtime是kernel的牆上時間,記錄從1970-1-1至今的時間差,不管是使用者空間還是核心空間要獲取的系統時間都需要去讀取xtime。
2)timer中斷模式
kernel下timer的中斷模式支援2種:週期性和一次性,也就是periodic和oneshot。
對於固定tick(1/hz)系統的timer使用periodic。但是對於tickless系統,則必須要使用oneshot 模式了,因為每次timer中斷間隔不一樣長。
3系統啟動時讀取硬體時間,一般在rtc驅動載入後,呼叫rtc_hctosys()(driver/rtc/hctosys.c)。其根據核心配置config_rtc_hctosys來決定是否同步時間,並讀取config_rtc_hctosys_device(一般為rtc0)來獲取rtc時間。
late_initcall(rtc_hctosys);
參考:
MC9S12G時鐘配置
一 enable外部時鐘 使cpmuosc暫存器的osce位置一 二 計算需要的頻率 以24mhz為例 pllclk 24mhz 2 x oscclk 振盪器頻率,即你的外部晶振 x synr 1 refdv 1 三 計算出synr,refdv後 把synr得值賦給cpmusynr的前六位,把ref...
Oracle9i 10g 樹查詢特性
例子 select select id from test where level a.lv start with id a.id connect by id prior f id f id,idfrom select id,level lvfrom test connect by id fid a...
ORACLE 10g 安裝中的TCP IP核心警告
在虛擬機器vmware6.5的rhel4上安裝oracle 10g時,先決條件檢查中核心引數檢查出現警告.其中的引數均為tcp ip rmem default 預設的接收視窗大小 rmem max 接收視窗的最大大小 wmem default 預設的傳送視窗大小 wmem max 傳送視窗的最大大小...