|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
6 Z- d# b! @7 u' ~1 C
内核版本2.6.30
3 n- M4 {9 n+ V8 ]/ R* n1 U4 x0 A
CPU:S3C2440
8 |+ e! \8 [) V: q
8 X) y- j. d+ |0 f: w. K. P( ^+ W) h( ~: B" G
/ ~: e6 t& [6 b; e7 y m
本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。4 c( Q- Z: n0 J# G
$ I1 ]. X' ] r/ I# o2 [
3 ]( J: K4 m: ^( `+ y) O; ?
( {4 R0 P L% t5 r* y) cARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。: U f+ t$ s) U9 k7 W
5 X' g' R& h- x$ s$ T0 V
/*
% W* x V3 x; l2 Z; J% K$ ?4 u * This is our kernel timer structure.8 Y6 g# K( ^1 R
*
; g T/ R3 L U) c! m+ ] * - init
+ h5 l/ ?. k6 A, e6 a5 `8 R * Initialise the kernels jiffy timer source, claim interrupt
. o6 |: {& ^( w2 h Q * using setup_irq. This is called early on during initialisation- g2 H1 a( q" R* Q! Q; Q
* while interrupts are still disabled on the local CPU.
5 h( k3 m. I- B8 T$ t, U5 o4 @ * - suspend
; `# b) ?6 t Z * Suspend the kernel jiffy timer source, if necessary. This: T$ i3 ^ p/ K& [4 s7 Q1 M3 k
* is called with interrupts disabled, after all normal devices1 p3 [! Z, P0 k
* have been suspended. If no action is required, set this to; G6 {5 H l8 t2 C& w+ ?. \
* NULL.) `2 s) _$ m* B J5 `0 R+ k; w/ N
* - resume
4 W" r- L |) Z * Resume the kernel jiffy timer source, if necessary. This3 j1 ^1 w6 n! I+ O( p/ e# {
* is called with interrupts disabled before any normal devices
" A" W7 m% B5 F* S5 ?8 e9 Z4 z! [ * are resumed. If no action is required, set this to NULL.
1 r( q- R: E; y* q, B/ n: w" A * - offset
. L8 V, d$ U9 L/ r, e * Return the timer offset in microseconds since the last timer
, {! U3 W* I" L6 n$ @1 ^. q) K1 A& I * interrupt. Note: this must take account of any unprocessed
4 `: ~5 l2 T6 p# I f3 J+ l * timer interrupt which may be pending.
1 f4 x! l! d- E& e Y' \8 Y */
( g% y- v4 x6 o/ N9 m" E& }; cstruct sys_timer {' ?6 l, r- h9 {, k, j% E8 Q- y
struct sys_device dev;
& t, G' z# T0 @) p* c+ F6 p& A void (*init)(void);
& u5 l$ P8 a# u8 U9 s! w+ A2 E6 H void (*suspend)(void);
7 v% Q, m# M a( O5 U: y void (*resume)(void);
) d% O( g0 v2 a5 z# T#ifndef CONFIG_GENERIC_TIME; d% l$ T) y; e: q) D; @/ r8 ]
unsigned long (*offset)(void);% z% v2 a+ N) G7 W9 P$ j8 }
#endif* [- a2 u& o8 p
};
a3 |) @4 X& {9 O: |# @: @. i/ d: L4 e$ R
S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。# W" L6 c/ ~2 |. b5 h
struct sys_timer s3c24xx_timer = {/ |8 H3 H. j9 h) o
.init = s3c2410_timer_init," ` J, X/ s+ R- ]( [" D" s H: O0 u
.offset = s3c2410_gettimeoffset,; V1 h1 e0 t! u) E, A
.resume = s3c2410_timer_setup* ]* `3 R% v# }
};
) \( S$ a8 o8 g# {7 b1 B0 m+ [; o& e$ i! R
如何将该定时器告知内核呢?7 l( @2 \1 S. u$ [# v% Q
在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏
' n a/ s1 H {6 T3 w" x- Z9 L' @4 \8 v/ ?
MACHINE_START(S3C2440, "SMDK2440")
, K$ s" J2 P2 {! q) \ /* Maintainer: Ben Dooks <ben@fluff.org> */ E* R. E# ~/ G$ _8 D/ z: d
.phys_io = S3C2410_PA_UART,# E8 j0 R( V! K
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,7 }) `1 x7 x+ J9 T: t& [. m1 M/ _, t1 O
.boot_params = S3C2410_SDRAM_PA + 0x100,
8 r; I+ Y$ w7 C& F K( ]9 s $ C# g/ L M* y, |9 Y# `" S, q
.init_irq = s3c24xx_init_irq,
( r4 ?( Y+ j6 ^8 @0 {7 A% a) p .map_io = smdk2440_map_io,. h" Q* K' ^/ w6 V8 Z, d
.init_machine = smdk2440_machine_init,' v, Z4 B3 X3 H# z) A! D# \: i3 F
.timer = &s3c24xx_timer,
" T& Y: d% s8 UMACHINE_END
$ {3 N0 _: b2 N. d
`0 o9 ^( T* I; q; ^" M该宏用于初始化结构体struct machine_desc,结构体成员如下:
) s% g4 Z; H3 B3 pstruct machine_desc {3 C2 J! w- y) N$ P2 @
/*
N6 L0 N7 X( |/ A * Note! The first four elements are used
% ?, w$ I) B3 i8 M/ b( {" y * by assembler code in head.S, head-common.S
/ I- Q+ X9 \/ T, D6 F! K( w */. X6 T* Q; a( G6 W% I N
unsigned int nr; /* architecture number */
9 ?8 O6 s$ o' D unsigned int phys_io; /* start of physical io */
6 | Z2 n! R5 R, {8 z. z unsigned int io_pg_offst; /* byte offset for io
& O- Z! \: h: T& y * page tabe entry */
4 l- g0 H) ]7 O7 A ) u' B, Z( E# v
const char *name; /* architecture name */2 p' | Z3 a/ G, a7 @0 [7 w5 {* F! @
unsigned long boot_params; /* tagged list */
' O2 @% s" ^. S0 m( u+ {( v ! c: h1 h! S3 i+ j8 R- a' g
unsigned int video_start; /* start of video RAM */% W6 U0 I# J+ S" X3 W( _
unsigned int video_end; /* end of video RAM */3 ]4 b2 ~' I* x; q5 W1 G
( m# r- f3 Y+ Y1 w
unsigned int reserve_lp0 :1; /* never has lp0 */* k" v2 c$ |7 Y$ E7 u. [2 ]( c
unsigned int reserve_lp1 :1; /* never has lp1 */. R! U) Q: I# x K
unsigned int reserve_lp2 :1; /* never has lp2 */4 T: d+ |! _7 A' E
unsigned int soft_reboot :1; /* soft reboot */ o, W- P* f* x! \
void (*fixup)(struct machine_desc *,/ }$ G. \) e1 M; K! ^1 |
struct tag *, char **," l, \, m5 W0 L9 q& D5 j
struct meminfo *);* o( b$ H* _6 I1 x/ ^; e5 s) P- J
void (*map_io)(void);/* IO mapping function */1 Y5 V, @( _- @
void (*init_irq)(void);
) {4 }; @1 Q' J$ i2 L2 L struct sys_timer *timer; /* system tick timer */
3 `- G5 b) `7 d void (*init_machine)(void);
* Z# M6 b6 ^+ ]) b5 W% L};
7 `7 i( U7 s1 j# }( Y3 ?" y3 j% v7 a, V% g Q8 i
在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。, U4 ?3 f! z! l
接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
! Y2 m9 K' t* h, w3 Y4 I: K( h7 g2 C5 s: q# \* p( T N
system_timer = mdesc->timer;9 d4 Z/ [# m$ Y0 J _8 V
9 x( R# Y7 k( c6 A: |mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。
" ~7 \4 L! F0 W
8 j3 z* e: V% y4 y" p最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:5 C/ f* q& P6 w; l8 Z7 {* w# `
3 l, O& _& ~, x$ i
start_kernel ()--> time_init() --> system_timer->init()4 Y/ z w0 v7 S7 C. X7 |7 g: c
4 i2 K. J+ D0 _! Z
time_init -函数位于linux/arch/arm/kernel/time.c。6 K9 T' W4 ~1 Y$ V
" S& m' ]* L) I0 T# Y c3 X9 W: ~8 p \& t+ l, D# h
y( Q6 M: J0 w9 ~7 C# O/ X0 W* Y' K1 w. w" R0 O" F
+ w7 Q% X. X @' I6 a
, n n% |1 r1 o% F
$ K& d7 B7 K' y- c! \, q) |0 g
|
|