|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
* L# C: U. @8 Z- @( _ q
内核版本2.6.30
8 \! r, m7 o; o2 g, o) T0 r6 W" S& u
CPU:S3C2440
9 L7 q( H0 L; P6 F. J1 ?0 Z
( s. c' T6 Q6 \5 U6 {, @) {
: C* D7 y9 S |$ h6 ]( X
; [" `# m3 W6 W6 Y" h本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。
8 Z f# p/ y/ d3 t" |1 C2 G7 f, l! F1 Z1 Q) K) J
* T$ [2 L7 l: C% N/ l# {$ M' p" I% R+ o+ W
ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。6 Q4 u$ K& ?9 n* M8 T
" @3 ~( P* T4 U# l7 Q" B5 }
/*
+ S0 e# M: F [. t- W7 f. m * This is our kernel timer structure.
, B7 s# B J" Y; U: @* }/ ~: O *
. C' K( E9 Q0 E1 T/ U * - init" g" F/ T- g3 C, {2 T" I8 l
* Initialise the kernels jiffy timer source, claim interrupt2 g+ P, Y, [ P
* using setup_irq. This is called early on during initialisation
) e1 |6 _$ T; Q6 s: | * while interrupts are still disabled on the local CPU.1 L) f5 p8 s7 d% u7 E& o
* - suspend
6 I3 H% _8 c+ N7 O: G* Y) v * Suspend the kernel jiffy timer source, if necessary. This
! x2 Z7 g( M l! Z * is called with interrupts disabled, after all normal devices, P$ i! o. I. V; \4 \4 T, t+ t/ o
* have been suspended. If no action is required, set this to6 e9 @! s% Z1 C8 {. z: w
* NULL.
+ O& @( n+ m) Y# k1 m8 |, q * - resume6 L* [2 V9 W" S
* Resume the kernel jiffy timer source, if necessary. This
. D! g6 s0 D' ?# z9 F; \& d * is called with interrupts disabled before any normal devices" M( k0 m) f9 `& }$ z0 W
* are resumed. If no action is required, set this to NULL.
8 m9 g0 P% t. [8 M * - offset3 I$ D+ e# N, A' w
* Return the timer offset in microseconds since the last timer
* T: }* J% F6 S2 L/ T * interrupt. Note: this must take account of any unprocessed' d( s6 O0 d0 J! L* Q) x1 {* W# O. E' ?
* timer interrupt which may be pending.
; i+ |0 [" M x */
% j7 Q$ S6 x& @; [' b. Y: a& wstruct sys_timer {
2 [# a: h5 T' n- _8 L struct sys_device dev;1 D; `5 b/ G; V2 [% y
void (*init)(void);2 e6 d/ k& J, ~, H- P5 F {. o
void (*suspend)(void);' ]1 N$ }3 L4 z4 K+ ~8 A
void (*resume)(void);( K9 P( M: `2 a6 v- s. n
#ifndef CONFIG_GENERIC_TIME
( h3 _4 T, H1 w$ R1 a unsigned long (*offset)(void);; Z6 J+ B, v9 P9 a
#endif
) a% Z$ x$ Z w4 C};- B8 _# l" W7 n: ^, s
/ r. u+ s0 P8 bS3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。
2 ~. `7 i( `' [struct sys_timer s3c24xx_timer = {- k) _1 f& ]* w0 L3 N
.init = s3c2410_timer_init,
( V$ S- L m( l$ g .offset = s3c2410_gettimeoffset,6 S, {4 Q& r" W
.resume = s3c2410_timer_setup
- C5 y8 r/ e6 W( N};/ N* g/ a& E1 |/ O( O# }9 U# f
) w- E' Y; V1 G
如何将该定时器告知内核呢?
- R: Z* \. L) X: T2 z在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏1 _8 Z( b* @1 u L X0 D* O) h
# N3 h7 L9 Y, B% g9 D* ^7 I+ [2 f
MACHINE_START(S3C2440, "SMDK2440")+ ^( b: ?7 o6 b+ f) y; |
/* Maintainer: Ben Dooks <ben@fluff.org> */
% {5 c# |, |; S, m& z0 P .phys_io = S3C2410_PA_UART, k( j9 R% q& c7 r8 x7 \- r; T9 s2 X
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,! C- g+ V4 V9 o ~/ D
.boot_params = S3C2410_SDRAM_PA + 0x100,1 ?8 ]! c6 x7 r+ c
o5 y2 c0 {: e$ A
.init_irq = s3c24xx_init_irq,4 g7 ]5 Z+ E) e' {
.map_io = smdk2440_map_io,
2 a5 R, x1 x! J7 @% { k6 S .init_machine = smdk2440_machine_init,. G4 h4 r6 y9 ~8 p
.timer = &s3c24xx_timer,) E$ w6 n+ _' X% K1 n4 C
MACHINE_END
& B, P5 t( J3 c. f5 \
6 B5 L. Q' e _该宏用于初始化结构体struct machine_desc,结构体成员如下:8 F, c6 ]/ e/ r) H5 \- M
struct machine_desc {- f9 ?. x! G7 V4 z4 T9 \
/*
8 S) f* P/ b! M# H$ F0 } * Note! The first four elements are used
5 p! r. f q* R- C4 ] * by assembler code in head.S, head-common.S: y# v; p: y- E4 }9 C
*/
$ Q1 {5 S2 S$ u6 a* r) `1 X# } unsigned int nr; /* architecture number */# _; ]$ b+ _. z4 X
unsigned int phys_io; /* start of physical io */3 ^. D7 l, i7 h9 O
unsigned int io_pg_offst; /* byte offset for io + k4 W1 w2 z7 [3 l f, b3 Z
* page tabe entry */7 U7 H: @" p2 W3 c5 G3 m
0 E$ k3 Z+ B) ?4 C const char *name; /* architecture name */; B9 d) A% [* t a
unsigned long boot_params; /* tagged list */
) E k1 ^2 o! j% `' x; v
* F2 H: a4 V7 _; H( w# Q1 E unsigned int video_start; /* start of video RAM */
. N ]% f) |0 {$ v" _ unsigned int video_end; /* end of video RAM */
W$ @% f2 \4 u* W 8 k5 g+ f+ e( W. l
unsigned int reserve_lp0 :1; /* never has lp0 */2 `" }, H9 Z7 z: y
unsigned int reserve_lp1 :1; /* never has lp1 */
# i( z% _1 I2 Z/ Z7 T; h$ f, r unsigned int reserve_lp2 :1; /* never has lp2 */
# d0 S* J+ o% V) J unsigned int soft_reboot :1; /* soft reboot */7 v- ~$ j5 X- @& B
void (*fixup)(struct machine_desc *,
5 Y* _& y2 I! v! w struct tag *, char **,
1 c6 n( Z; ^( R+ a struct meminfo *);' a" z" C' ~+ v" Y6 W1 K3 f- Z
void (*map_io)(void);/* IO mapping function */
: R6 m$ W8 H+ k4 m2 G3 N, U void (*init_irq)(void);0 ^( q1 q" r$ H' @& A1 ^( D
struct sys_timer *timer; /* system tick timer */7 r [8 v; b/ O! N2 Z1 v' u: P7 B h
void (*init_machine)(void);
4 G+ k' i4 F1 E. f};
; K$ ^+ L5 ~9 f( |4 |3 y/ t0 Z9 k: X# l0 O, B0 c
在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。
; o% Y3 W0 {: t5 D, u3 i3 Y接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:1 t: d" M$ M3 b2 L
3 e" |1 n9 Z6 ] system_timer = mdesc->timer;8 M: `) r. u: }6 k1 r
8 U6 q( [3 M5 h5 P
mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。
; H& W* c2 k, X7 @5 g g( y% P! i: r. N' ^; {, ?. s
最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:
2 |4 w1 V& ]7 ]$ R3 q) y, \. X6 `5 S1 G; _. L+ `) q! t& x5 B+ C
start_kernel ()--> time_init() --> system_timer->init()
: E# }& b% T5 k4 M* Z# `, n8 z$ I/ q, s. a8 {/ ^0 R' c
time_init -函数位于linux/arch/arm/kernel/time.c。
2 A7 n* z, t# W9 v' L; k/ s; Q; Q/ ~& l# r* g4 ^ _
{. i4 x+ H( ` p5 e& o4 y5 c) A
6 e$ p% M+ k- ]$ d/ ?+ a. _1 u( y- [+ P9 o4 s
4 i4 w2 v4 R" _ H g
" d R' Y+ N& M( V9 V$ i& p: I) K' G' w
|
|