1、核心時鐘
作業系統的核心都需要乙個系統時鐘才可以工作,這個系統時鐘是硬體提供的,作業系統用該時鐘進行計時,如sleep()、時間片輪轉。
作業系統核心使用的時鐘,叫核心時鐘,也叫滴答時鐘。
stm32f407 + uc/os-iii ---->作業系統核心時鐘頻率:os_ticks_per_sec = 200
s5p6818 + linux ---->作業系統核心時鐘頻率:hz = 1000
linux的核心時鐘,是由處理器的定時器提供的。
2、核心時鐘的頻率是與硬體平台相關
s5p6818 + linux —>如何初始化linux核心時鐘的???
1)首先找到linux原始碼針對s5p6818平台的主初始化原始檔:
/arch/arm/mach-s5p6818/cpu.c
2)找到機器巨集
machine_start
(s5p6818, cfg_sys_cpu_name)
.atag_offset =
0x00000100
,.fixup = cpu_fixup,
.map_io = cpu_map_io,
.init_irq = nxp_cpu_irq_init,
.handle_irq = gic_handle_irq,
.timer =
&nxp_cpu_sys_timer,
.init_machine = cpu_init_machine,
#if defined config_cma && defined config_ion
.reserve = cpu_mem_reserve,
#endif
machine_end
機器巨集中,定義了一些資料和函式,這些資料和函式在linux核心初始化的時候,都是針對乙個具體的硬體平台的。
每個硬體平台都有乙個這樣的機器巨集。
3)找到系統時鐘的定義
.timer =
&nxp_cpu_sys_timer,
struct sys_timer nxp_cpu_sys_timer =
;
4)找到定時器的初始化函式–>timer_initialize
static
void __init timer_initialize
(void
)
5)timer_source_init(cfg_timer_sys_tick_ch); //0
猜測使用的是timer0作為核心時鐘。
3、核心時鐘的頻率
stm32f407 + uc/os-iii ---->作業系統核心時鐘頻率:os_ticks_per_sec = 200
s5p6818 + linux ---->作業系統核心時鐘頻率:hz = 1000
核心時鐘的頻率與處理器的效能有關係。一般處理器的效能越高,hz的值可以設的大一些。
hz的值越大,有什麼優缺點??
系統計時的精度會越高,計時越準確,系統的實時性越好。系統處理時鐘中斷的頻率越高,系統的負擔就越重。
1、hz是乙個全域性的常數
hz就是linux核心時鐘的頻率,hz是linux系統中的乙個常數,當配置核心的時候,hz的就設好了,如果重新修改hz的值,重新配置、編譯linux核心。
printk
("hz=%d\n"
, hz)
;
2、如何設定hz的值
system type —>
timer frequency (1000 hz) —>
( ) 100 hz
( ) 250 hz
( ) 300 hz
(x) 1000 hz
條件編譯選項:config_hz_1000
去核心原始碼搜尋
$ grep hz_1000 ./ -r
3.hz的定義
define hz config_hz /* internal kernel timer frequency */
//.config --->autoconf.h
#define config_hz 1000
1、什麼是jiffies
jiffies是乙個全域性的變數,記錄了linux核心從啟動到現在經過了多少核心時鐘週期。1秒鐘內,jiffies增加hz次。
jiffies是核心時鐘的計數值。
jiffies/hz ---->linux系統啟動到現在用了多少秒。
printk
("jiffies=%lu\n"
,jiffies)
;
2、jiffies的定義
jiffies = jiffies_64;
u64 __jiffy_data jiffies_64;
unsigned
long
volatile __jiffy_data jiffies;
注意:
char — 8bits
short — 16bits
int ---- 32bits
long ---- 問題:cpu是64bits,但是編譯器是32bits —>long = 32bits
1、應用程式的延時函式 —>會產生阻塞
#include
unsigned
intsleep
(unsigned
int seconds)
;int
usleep
(useconds_t usec)
;
2、驅動程式的延時函式–>睡眠延時(會產生阻塞)—>長時間延時
#include
void
ssleep
(unsigned
int seconds)
void
msleep
(unsigned
int msecs)
3、驅動程式的延時函式–>忙等待延時(不會產生阻塞)---->短時間延時
void
mdelay
(unsigned
long x)
void
ndelay
(unsigned
long x)
void
udelay
(unsigned
long x)
|------------------|
_____
int data;
int timer_cnt =0;
dowhile
(data ==0)
;dowhile
(data ==1)
;得到timer_cnt,就是us的計時值
。
linu核心動態定時器是依賴於linux核心時鐘的,動態定時器的週期只能是核心時鐘週期的整數倍。
動態定時器不是硬體定時器的驅動,而是利用核心動態定時器產生的時鐘週期。
1、定義乙個動態定時器
#include
struct timer_list
;
例:
static
struct timer_list gec6818_timer;
2、初始化動態定時器
void
init_timer
(struct timer_list *timer)
設定動態定時器的超時時間和超時處理函式
void
gec6818_timer_fun
(unsigned
long data)
//data=10
gec6818_timer.function = gec6818_timer_fun;
gec6818_timer.expires = jiffies +
100;
//當前時間開始,100個jiffy後,會產生超時(100ms)
gec6818_timer.data =
10;
3、將動態定時器加入核心,並啟動動態定時器
void
add_timer
(struct timer_list *timer)
4、修改動態定時器的超時時間,並啟動timer
int
mod_timer
(struct timer_list *timer,
unsigned
long expires)
5、刪除動態定時器
int
del_timer
(struct timer_list *timer)
示例**:led_dev.c Linux核心時鐘框架
逢山開路 遇水架橋,今天想自己寫個adc的驅動,發現不清楚系統各個模組的系統時鐘如何使用。總不能自己想怎麼弄,就怎麼弄吧,還是學學框架吧 使用時鐘的框架。adc clock clk get null,adc if adc clock clk use adc clock clk enable adc ...
linux核心的rtc時鐘配置
linux核心的rtc時鐘配置,見device drivers real time clock 我們的rtc主要是有三種介面配置,一種是i2c介面,一種是spi介面,還有就是cpu自帶rtc時鐘晶元。推薦配置如下 i2c介面rtc時鐘支援晶元 dallas maxim ds1307 37 38 39...
深入Linux核心架構筆記 動態時鐘
為節省系統功耗,只在有些任務需要實際執行時,才啟用週期時鐘,否則會臨時禁用週期時鐘,對該技術的支援可以在編譯時選擇,啟用此選項的系統也稱無時鐘系統。判斷原則 當系統排程選擇idle程序來執行時,動態時鐘系統會禁用週期時鐘,直到下乙個定時器即將到期為止 struct tich sched idle t...