|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
6 R3 c/ X' `( }: O6 F+ G$ X8 ?. r
内核版本2.6.30/ x/ R( R: Z/ N: Z
0 s, f# }9 X+ w+ @& I0 ECPU:S3C2440
* \* V' v S f2 S% I+ w+ b% P/ x: V% l! F# k; B
! Q4 Q1 C. ^! w
% l9 H: G7 i. W7 w5 u6 B+ r! ^. K! @" U
本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。' i) F; K% l& W
2 y" m- {. Z( [; H {- v
( U/ m Z: f8 D5 S& }/ y! H5 @' y) f' ~0 l$ t- ?
ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。$ B4 c9 ^/ u; k* y9 u. l
! C3 @! |$ G: y+ @, l) E/*
4 e# L D4 w3 s! R" w/ X! k * This is our kernel timer structure.
( Z. Y1 v- G4 A0 A0 L# U *
* L# Z% \ F2 u3 i2 m * - init* U4 I% g0 k6 o, k& j. N& E) P
* Initialise the kernels jiffy timer source, claim interrupt
# F& {$ J. f/ c4 X: S4 r, u * using setup_irq. This is called early on during initialisation
: \% e Z$ z1 c" d* j * while interrupts are still disabled on the local CPU.- L: u/ i: o: a, V' i( ?2 b+ N
* - suspend
1 _# o, {- ~! u4 w * Suspend the kernel jiffy timer source, if necessary. This
1 n" w( t' J! m6 s * is called with interrupts disabled, after all normal devices- G( V* O/ |7 B- P6 O
* have been suspended. If no action is required, set this to! T F" t, a" i8 R; `
* NULL.1 `8 s" }" R8 U; i% p2 o6 }
* - resume1 ]5 H) E+ P% w! i2 a, u% v) G% V
* Resume the kernel jiffy timer source, if necessary. This
0 Z+ l! F- K9 z g * is called with interrupts disabled before any normal devices
4 y- U; u S. D * are resumed. If no action is required, set this to NULL.8 ]( r# @3 V: r8 _; ~- Q7 d
* - offset: y2 j) P% t, m5 o' K* t; `
* Return the timer offset in microseconds since the last timer1 t0 ? g [9 `( d$ I+ Y; M5 V; d$ {
* interrupt. Note: this must take account of any unprocessed
& _# i: {2 F' N! s; t p * timer interrupt which may be pending. V, U6 i' Q" w8 K- ~
*/
/ V8 z5 a/ P) H# X+ Hstruct sys_timer {
, {2 L+ B6 C# z l& f X struct sys_device dev;% R( P, M, u. C1 |
void (*init)(void);
5 @- B4 k' ]6 F3 R void (*suspend)(void);& S8 x) A/ j# z( D( k3 A) z
void (*resume)(void);1 P! M K* o( c4 a1 V
#ifndef CONFIG_GENERIC_TIME
, K h6 P9 B6 z) z4 Y/ u unsigned long (*offset)(void); F+ E" \' m+ ^9 i8 L7 `8 t7 B
#endif
) s4 M9 {& Z; ]};
9 p* }2 R' U9 x: o# K* z! g. X/ ~) t2 K
S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。4 e3 j0 C$ B% A9 m# g
struct sys_timer s3c24xx_timer = {
5 l7 A5 T* S2 X* y; \ .init = s3c2410_timer_init,
) k# E% x; ] g" _7 u1 U' u' B .offset = s3c2410_gettimeoffset,
7 K& I3 F, @5 E5 a2 Y1 L2 r5 l- T .resume = s3c2410_timer_setup
( s/ u6 M6 N/ k7 t};6 Q9 h" x0 T D9 {, ^! s" b
5 `6 F2 P4 ^4 N% n# s$ I9 o4 y' B( k如何将该定时器告知内核呢?
% j# _6 o7 |- l在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏
4 l+ J1 ^6 Y- w2 L( X4 p y1 }: H3 J+ O3 u7 K9 s
MACHINE_START(S3C2440, "SMDK2440")
& \3 v3 I- F+ E4 Y; B+ B: I0 ~ /* Maintainer: Ben Dooks <ben@fluff.org> *// F4 F7 n/ y( m$ W+ d* B- f, k9 G3 e
.phys_io = S3C2410_PA_UART,
1 r! v' r a% O* p .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,' |7 s& v' ~0 j5 H! b8 t
.boot_params = S3C2410_SDRAM_PA + 0x100,) T1 \# I& p7 w2 ~
0 b7 w" ~4 d' }8 k7 i/ e .init_irq = s3c24xx_init_irq,# v# q, i- o8 L7 k4 l: h) u, u
.map_io = smdk2440_map_io,
( @5 Q5 V1 b6 @; l+ x2 R .init_machine = smdk2440_machine_init,
6 |/ x. j3 j9 T! n+ F, ]/ n' R5 b .timer = &s3c24xx_timer,8 {+ w# Z, A7 S# r# x8 U
MACHINE_END
! l8 V q( U# P+ e1 H% O. P1 ?2 [7 i4 }
该宏用于初始化结构体struct machine_desc,结构体成员如下:
$ k: f/ i+ h; n f5 T+ _' tstruct machine_desc {" k! l4 \( h+ F/ r
/*
0 w b, w0 x+ `% j; P2 P J* l+ I; X * Note! The first four elements are used' M# U! V1 P/ ^( `3 _
* by assembler code in head.S, head-common.S3 y% ]; K% _7 _) ?7 }- p
*/
1 c; U+ G% |- J; |4 X unsigned int nr; /* architecture number */
* Z( v n: A% L* i5 { unsigned int phys_io; /* start of physical io */
' s8 L: K$ [% T: [5 @& l$ J unsigned int io_pg_offst; /* byte offset for io
: K- }! G' _, A: {: H4 y# t * page tabe entry */
7 [( Z) [" L% f+ _. T) R) x+ F . J& y& f4 ~+ |
const char *name; /* architecture name */. Z) V- j4 K; E: n3 `6 B9 F
unsigned long boot_params; /* tagged list */
- n! E' }9 A9 j% u
. ?) W8 L8 P5 I0 d unsigned int video_start; /* start of video RAM */
& V* @, ^8 }0 u9 P unsigned int video_end; /* end of video RAM */
( \9 W) d, K1 I# |3 ?: t/ @ T% @) f
1 B5 I* I0 V) o unsigned int reserve_lp0 :1; /* never has lp0 */
( d6 X% X, c% s P; Z1 } unsigned int reserve_lp1 :1; /* never has lp1 */: U9 N R+ a; }: v2 a
unsigned int reserve_lp2 :1; /* never has lp2 */1 k2 b* ^, v1 R- \
unsigned int soft_reboot :1; /* soft reboot */. p6 N8 P( H2 X5 k2 [
void (*fixup)(struct machine_desc *,
& P k/ g- H1 O: Z9 G6 X: s struct tag *, char **,
/ i0 p9 S% s7 {1 F struct meminfo *);' d c) V! j6 x5 }( |1 C
void (*map_io)(void);/* IO mapping function */+ T! H, j Z! v& Q. q* Y# t
void (*init_irq)(void);, x) \6 x/ \2 l) N
struct sys_timer *timer; /* system tick timer */' v1 K$ c8 `3 \+ I8 F r* j/ h3 _
void (*init_machine)(void);
) d6 `& ~4 m6 e2 m/ t E) {};& B4 W! h; |9 r6 t* P( ^; Y, W
; @, _0 y6 h! l: g7 T在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。2 q0 Z# y5 {# a6 m3 g! x
接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:- b5 e2 r5 I. p# a& \5 U5 x
5 s1 f. a! X' i system_timer = mdesc->timer;
; z1 ]4 K! `2 z j) l2 y$ d. w! ]6 v5 p# ^0 ?% P$ c; M% k
mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。
1 v8 b! t9 X, s: d; w0 g, C$ i6 U% K3 J+ c/ Y6 O; `+ @
最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:
! |. L- f& X6 J4 m: ~
$ ]5 p0 F5 j3 g C d! O: _+ e7 H" cstart_kernel ()--> time_init() --> system_timer->init()6 i9 N, P$ _% w* z7 ^) |
( R) R" S5 J3 L7 x) E9 Dtime_init -函数位于linux/arch/arm/kernel/time.c。! l" G, H1 Z1 @& q5 p9 E
, r @4 ~1 N, p% _) |' ]
7 D, `% V- U* J: N3 r# j# c n! ~6 \) H4 B; m0 b
7 w6 W+ J( B5 V
, t4 A: e3 c* v9 w5 ~8 [2 `0 @2 r& q. F* N- q
" L* M! B# O e
|
|