|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
1 W2 q' p7 v/ c9 G! S
内核版本2.6.30
; o* V9 q0 p; f2 _! f+ J! ?; B+ q- G
CPU:S3C2440
) b1 m7 s& s4 E- o
7 {4 j4 Q6 o9 Z% g. ?( |$ u: E5 c6 y' t( q
7 X* ^0 _, f9 d) s9 m- y0 H
本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。+ R) ?( |4 j" v$ _! ~
- {8 p2 L: b- k$ n
4 |& m; W5 G" r
6 P5 C4 H1 q. |ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。2 @ t3 J6 ~' G
4 F- j/ h8 `# m' W- t/*0 @* q) x( @6 ]6 n, ? R
* This is our kernel timer structure.
# ~" u) I: c# m/ H3 s4 G, P *% ^% C: {/ L6 j
* - init; ~" Y) E- ~1 k; p2 Z) ^7 z
* Initialise the kernels jiffy timer source, claim interrupt
$ I" r* \$ r2 g7 O * using setup_irq. This is called early on during initialisation
! ? y4 a2 P# h, K3 W * while interrupts are still disabled on the local CPU.1 I( y" K: ~ ?$ S/ P& p2 x4 W
* - suspend( x, b$ |* Z2 J1 _9 X" I
* Suspend the kernel jiffy timer source, if necessary. This
6 o/ L) w5 p" h. V * is called with interrupts disabled, after all normal devices
; f4 z( C% T9 D* z( r+ V4 D * have been suspended. If no action is required, set this to1 u. x3 n: X5 U" D0 u
* NULL.
$ \# ?+ R8 F7 z/ R * - resume
8 N2 ]# O/ |! `0 \, ^; Z7 h * Resume the kernel jiffy timer source, if necessary. This7 @; m" L( a" `5 X* e, [9 g: M
* is called with interrupts disabled before any normal devices
+ H: i/ N' h; |% f7 w4 u * are resumed. If no action is required, set this to NULL.$ z+ M1 I& z3 V8 O! L6 O
* - offset4 k$ b$ o0 q# x( I& k
* Return the timer offset in microseconds since the last timer' W. X' ^, {) R: _: B
* interrupt. Note: this must take account of any unprocessed; L. \" G9 G% z( N
* timer interrupt which may be pending.$ h+ b0 H) r. t c/ q
*/
6 T1 A- c3 M4 r! A" o [: U Tstruct sys_timer {# x( N4 C5 p% e$ \
struct sys_device dev;& |" z/ ] {( U' M x# e- G7 j5 \
void (*init)(void);
& w' I1 c, v! }3 _$ n- i- B J void (*suspend)(void);! a1 Q4 ^0 i2 S; D& i5 P2 E4 s
void (*resume)(void);" g) X, r3 {6 C2 l3 C
#ifndef CONFIG_GENERIC_TIME" j9 Y) y- E4 @% W# |$ c
unsigned long (*offset)(void);3 K7 I* M$ D# M: H
#endif' S# P: X" k6 V4 |3 p$ J5 }" P1 m1 h
};
7 m1 r( G# k! m/ ^7 h8 ]9 E1 @. D% z, L% u, y
S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。
1 {/ F8 `( k' \& Gstruct sys_timer s3c24xx_timer = { ]0 f- T' r& d$ c. s
.init = s3c2410_timer_init,
9 A! f0 ], Y6 y/ f .offset = s3c2410_gettimeoffset,
+ `8 I1 k2 I: s Z9 f .resume = s3c2410_timer_setup3 m2 \5 H. V; C
};
% e2 {* h2 X" k1 _" }
# Q, W9 W4 p. `如何将该定时器告知内核呢?
) U7 |& E; v3 c在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏' Q: U* O2 ?2 [9 C! ~' L
8 p& O2 w: V' j1 \' c- v& b9 ZMACHINE_START(S3C2440, "SMDK2440"); `% }' D. Y1 T7 T9 O ^
/* Maintainer: Ben Dooks <ben@fluff.org> */
( t5 V/ Q. {8 P! W .phys_io = S3C2410_PA_UART,# S! [8 J: F/ {0 y$ ?* V
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
" e) ]* r+ l |- A+ K .boot_params = S3C2410_SDRAM_PA + 0x100,
% W. j- [+ T$ O8 e% N
7 U7 y. ^- m, r1 e; z' U .init_irq = s3c24xx_init_irq,
- v: b! Z) W. F2 B1 N- t0 P .map_io = smdk2440_map_io,
: o% S/ X) {$ M( y. {" I. e$ t .init_machine = smdk2440_machine_init,
$ I* X. g( `' z! F, o; D .timer = &s3c24xx_timer,
/ u4 \* V/ F& ]MACHINE_END4 M7 u8 T) K1 C
: h# R; v* g! ?- M' ^6 n2 r' L( ]该宏用于初始化结构体struct machine_desc,结构体成员如下:5 E$ X1 K! k0 M7 r
struct machine_desc {8 O# M. @) u+ z9 T+ n: A N
/*
# p3 \7 F+ S" ^) c& w% P2 e; m * Note! The first four elements are used
. Y8 u. {$ q/ C" ] * by assembler code in head.S, head-common.S9 |/ V+ V2 n3 g0 Q
*/
; D* d1 l; `5 ?* _ unsigned int nr; /* architecture number */# e( P- }& C$ p, E: E" A2 Z; o. q
unsigned int phys_io; /* start of physical io *// b- F( |$ d0 t; ~& X a! u
unsigned int io_pg_offst; /* byte offset for io $ Z9 Z+ o% D! k) Q( }
* page tabe entry */: |; c# i$ `0 V% ?
4 s# N( M( G+ p3 @- G, R
const char *name; /* architecture name */
0 K2 A% O1 I& L9 [! p unsigned long boot_params; /* tagged list */& L! l1 N8 K% @! Z; G, a
7 t+ d$ m8 {7 g3 d* T& B1 i unsigned int video_start; /* start of video RAM */
5 i# r7 e5 |) l; L unsigned int video_end; /* end of video RAM */
% B) v* N! {9 k- Z+ ?0 E 7 T3 D8 m6 Q1 w2 i
unsigned int reserve_lp0 :1; /* never has lp0 */8 v! ]0 G V* D7 [' ], A4 n4 @! f
unsigned int reserve_lp1 :1; /* never has lp1 */
1 a( J8 |3 I7 Y, i) C: K+ v9 J unsigned int reserve_lp2 :1; /* never has lp2 */
+ z% Y3 i9 j. }1 e1 f$ W! i$ U unsigned int soft_reboot :1; /* soft reboot */
! R y1 I: H ], _8 j void (*fixup)(struct machine_desc *,# |; P6 O, }% K6 J! ]/ T
struct tag *, char **,0 W- B: j7 j- ~' O7 J! a
struct meminfo *);
8 h3 ` r, b# f B9 d void (*map_io)(void);/* IO mapping function */& I/ A' E: t* k- j4 A1 z6 y3 g
void (*init_irq)(void);
& K- `+ L' X/ s' H struct sys_timer *timer; /* system tick timer */7 @) ]+ s. U2 _5 T% i
void (*init_machine)(void);2 D+ v+ S" A4 g
};
6 E; C2 l. Q4 E
9 K4 N6 a7 \# Y, J' @在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。
; b) U- s/ C$ d$ b# F- @, X8 f接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
5 F9 I/ x- K" p `! d: N7 I# o2 b, r8 H% Z2 ?5 @ _7 W: [
system_timer = mdesc->timer;
, X* S% {$ S; A2 B: A
8 C0 W7 {4 T' c; H' x) a. g+ W& Ymdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。# O# u4 s6 B* k
2 T K: d$ D& t- L最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:
6 _4 b. g+ p, `9 r& Z3 K3 \5 p/ e/ e7 l# `
start_kernel ()--> time_init() --> system_timer->init()
$ N# U8 d- V9 {0 x, h) l" S8 e4 L$ M7 f" T2 ?) P
time_init -函数位于linux/arch/arm/kernel/time.c。9 `# x, ]# B% K2 Y
5 r) d" p) k/ J
: y4 c6 }* t5 c
7 F6 y$ v1 m9 m
. I6 m! r, u' J7 G5 G% F8 D( H5 o4 I: J0 ?: N
+ h# i; ^- W7 O3 @
, S3 j, o* H( Y1 x$ j: e
|
|