|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
. d/ B- x0 R# u4 U$ P内核版本2.6.30
! z2 ^; d2 X/ \; X g
' o/ U: ?; B3 y# i% K# p+ Z7 \6 _CPU:S3C2440
) q5 s- W$ Q7 n2 @) u+ b7 S; ^) l" G* x6 k1 [0 p) g& g9 e
- x, H S! f& G- h" t
2 P0 A/ J( A, T6 m本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。$ ~4 @- B# H @0 P
: ^. k, b. l& W! Y4 B5 \
K% S; l# q( a( v; G9 w f
. ^; ^4 K# D1 ]- T. Y5 B1 @
ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。
# u) F3 `0 | P/ Z8 n3 b. D
" W* K; k4 m& W" Q/*
5 p( a" W- U5 O * This is our kernel timer structure.
' J$ b4 F0 o" ?3 V. A *& w# f+ W7 e1 t
* - init/ I8 `" C9 Z' Z, n0 u
* Initialise the kernels jiffy timer source, claim interrupt
$ h1 Q A8 o7 c1 G# r5 c# R/ F * using setup_irq. This is called early on during initialisation
8 C6 C. e1 _: _ G8 b% P5 T * while interrupts are still disabled on the local CPU.
0 g0 k0 Z) s6 y0 ^+ X( l * - suspend
2 @# T' T0 \+ e! o0 n3 ~& E' H* [ * Suspend the kernel jiffy timer source, if necessary. This
( J* z+ t1 ^+ l% q# d$ i * is called with interrupts disabled, after all normal devices3 ]+ U- b# @# G3 w" ]4 h
* have been suspended. If no action is required, set this to
( s$ B% o! R9 O/ |" i- s5 S6 T. j * NULL.
) ` q8 d( D3 B2 Q5 j2 } * - resume% Z. w! w$ d! }- v3 ]% C/ X5 n) c
* Resume the kernel jiffy timer source, if necessary. This
' E+ }# j3 c6 J, G5 F * is called with interrupts disabled before any normal devices" Y3 J) f" J! ?4 c: q: k. i
* are resumed. If no action is required, set this to NULL.% ]9 q- D) e1 o! d+ L8 X
* - offset X5 E: Q# q; V* t# } o0 E
* Return the timer offset in microseconds since the last timer2 p' x# R8 ^, X! I( a
* interrupt. Note: this must take account of any unprocessed3 @: ~5 w! }+ Y4 W' z
* timer interrupt which may be pending.' D M0 P% { b# m: ?* P
*/
+ y" u* {0 f1 `$ U8 d; fstruct sys_timer {( A+ k0 I* C0 n) s
struct sys_device dev;
2 ^* [4 U% w% \ void (*init)(void);
6 S. s' w7 ~0 {; o void (*suspend)(void);
& Y v2 @, Y' W% ?$ X" f! U void (*resume)(void);& C8 C& ^' [- w, m
#ifndef CONFIG_GENERIC_TIME4 n) A: A6 d& |% ^/ J$ u7 m! N
unsigned long (*offset)(void);0 r0 j+ ?- `1 ~( S. A
#endif# M! z- m) U' C1 _' h
};1 @; ]! w, m3 z. z \
3 S+ P2 c8 i8 [S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。
% r& p% O2 k w9 a h4 Q% \7 istruct sys_timer s3c24xx_timer = {
' A# K, D# \0 s2 N# |- T& j6 t, S .init = s3c2410_timer_init,+ O' e" ` X; e+ r+ d
.offset = s3c2410_gettimeoffset,1 U+ b0 O- m n" A, d, {/ u
.resume = s3c2410_timer_setup
8 U- t% D6 u% I6 f* `- r};; v: Q: S4 [% _1 o) B6 J
4 P1 c1 r1 q8 T% A5 u
如何将该定时器告知内核呢?
; M! h0 s+ g; j+ U% w4 E( ~在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏/ U1 F |/ ]& a- s; G4 G# T
8 g2 R7 U g( Q* Q# a7 Q3 w. P+ z
MACHINE_START(S3C2440, "SMDK2440")9 [1 x6 y, S7 x& w i7 l' [5 T
/* Maintainer: Ben Dooks <ben@fluff.org> */
1 O: L( v: [. m .phys_io = S3C2410_PA_UART,2 V# q; P: d8 ~# d, c- f
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,' w) D/ n' j. t# T. O
.boot_params = S3C2410_SDRAM_PA + 0x100,* n" C/ w$ Y( v: o7 ?
. C2 S& R- R' X9 J
.init_irq = s3c24xx_init_irq,
8 f: \4 I+ [2 Y9 l% H7 z9 G .map_io = smdk2440_map_io,2 b" T. |7 X' \# M4 r
.init_machine = smdk2440_machine_init,7 J. r+ S! ]* a) ~
.timer = &s3c24xx_timer,/ l; i% y& Y# W4 _
MACHINE_END
1 v9 `0 h; T2 ]- [8 Y: u& J0 D- I$ l# G5 x: R6 o* D
该宏用于初始化结构体struct machine_desc,结构体成员如下:6 F# m) @6 L7 P" P' D( ~& K' e
struct machine_desc {
: {. V' u8 B* `+ P /*
* N, H5 x' s! q2 {. N/ {! I7 R8 N * Note! The first four elements are used1 R! M$ Y2 U: i" m# w R
* by assembler code in head.S, head-common.S# p9 H( |: ]3 D5 |. U
*/
# Q9 d+ }9 L, s9 y unsigned int nr; /* architecture number */! S4 A- q1 W8 f [
unsigned int phys_io; /* start of physical io */
9 f/ W! b- Q8 c" _/ e2 A unsigned int io_pg_offst; /* byte offset for io $ Q) Q/ s- P7 s1 D& k
* page tabe entry */
5 k* l! c7 p/ J3 P- K$ R [: S% F' J0 H6 s
const char *name; /* architecture name */
9 g* g9 j1 s- q/ D. v' I unsigned long boot_params; /* tagged list */$ t$ t* Z5 Z& G/ @% e8 \/ L/ z
! n& E/ i6 x- N' q unsigned int video_start; /* start of video RAM */% s* n( U4 s" H
unsigned int video_end; /* end of video RAM */
0 x/ X0 X, t$ K- R
+ i( k# J0 ~! M9 g1 Y1 A8 D& x unsigned int reserve_lp0 :1; /* never has lp0 */
8 [$ @9 _- d9 ^; D unsigned int reserve_lp1 :1; /* never has lp1 */% { d& s1 b* U( D
unsigned int reserve_lp2 :1; /* never has lp2 */
/ f3 u) w/ y( X5 E$ Y9 {1 w9 g unsigned int soft_reboot :1; /* soft reboot */
M7 Q" z) e& S8 G! `) W; P void (*fixup)(struct machine_desc *,5 D4 O- @& V6 ^$ E
struct tag *, char **,: ?5 M; _. g' r0 g: S4 c
struct meminfo *);1 p7 b# l# i2 e9 B3 P& X0 c
void (*map_io)(void);/* IO mapping function */, V* Q9 K1 E7 _" d" ^5 F+ v
void (*init_irq)(void);
4 C) \5 Z+ L! x- M }, p* c* t3 G' S struct sys_timer *timer; /* system tick timer */
, s, @7 X/ B0 V3 y) q5 h void (*init_machine)(void);
7 l- E8 M+ F3 [/ ~5 I' s};
" {: v7 p3 w0 u, i; ]
* H* s- s+ n% N在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。2 J4 [3 |) d5 B, J
接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
* v- t( K9 ~& C, d
$ }0 t2 M" q3 ]8 Y" a& S system_timer = mdesc->timer;1 d" d' l4 I B. ~
! y, T' }9 Q$ \; l1 a0 e
mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。
) }# I# w8 T/ \+ I, Q/ E6 ~3 o3 y! u& v* d
最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:+ R" y( C8 J, K. `2 C
/ F2 d) M( b4 R- L; D4 B
start_kernel ()--> time_init() --> system_timer->init()6 V1 J! y- A( m' t8 ]& d9 I
5 d2 q9 t# \9 @' M# o5 u
time_init -函数位于linux/arch/arm/kernel/time.c。: j X A0 ?1 g. p
7 u0 V4 H7 C; X5 R! R- s: W8 | B* m( Z7 Z5 ?8 x. a
! e7 b5 t/ b! B% M
7 a, c% p4 W4 z8 y; Q, b
4 r& K6 o/ r7 G$ H$ g" ]3 D) S. p% Y! ~" M- n
1 ^) W' \% S7 G R3 C V |
|