|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
, ?3 D9 |5 e5 X
内核版本2.6.30
% @7 l. t: g t9 C$ j1 e2 Y$ F9 @1 H# B* Z1 [7 x4 C1 Q) F
CPU:S3C2440- G3 g! R5 t+ O% @9 n8 D: o
& ?* G9 p" t- T5 d7 J. h
& u( | Z* ~. A7 ] @8 i0 b" _" V4 y( M' z4 z
本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。
' a3 y7 p$ [4 ?6 N2 T
! U5 n9 a# V J- F5 Q. h0 ?& {+ z6 d6 l" P0 t( E
9 t3 u7 p9 j, x( n2 d
ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。
: N3 f$ A: y6 U6 r6 N
2 J6 g# F+ [5 A# W; p3 L) N1 }/*
+ f- V& K9 ?, @" y! ]& z * This is our kernel timer structure.5 d/ i. M5 U* i4 z
*
( {( M! H7 P p2 R * - init
1 A3 j6 J& H7 \1 ?. a& r) Z * Initialise the kernels jiffy timer source, claim interrupt1 d' B9 H7 c4 v |/ S
* using setup_irq. This is called early on during initialisation
# Z' U- i- H: q# P9 Y" r * while interrupts are still disabled on the local CPU.
% ]! j1 X4 r/ Q7 k% r O * - suspend2 M; W- ?2 ^, V# v! A/ i$ b, r
* Suspend the kernel jiffy timer source, if necessary. This% x2 Y. E7 P% G4 t. ?
* is called with interrupts disabled, after all normal devices
- E$ V; [$ `1 }% n6 ` e7 y1 D * have been suspended. If no action is required, set this to
1 w. [/ i) i# v0 |4 C4 ^ * NULL.
2 l! j: v9 h7 l& W8 P8 z" Y * - resume. r I/ e7 S8 T8 k0 I4 t- o6 e
* Resume the kernel jiffy timer source, if necessary. This y/ Y$ N1 Q$ R8 ?2 y0 M
* is called with interrupts disabled before any normal devices
7 I( i. [5 H( y$ I3 o$ b- @3 G * are resumed. If no action is required, set this to NULL.$ F$ \3 j( g4 N& J3 o
* - offset: {( T; n& a! P! g8 B9 h$ @5 N+ z( o
* Return the timer offset in microseconds since the last timer) w2 K/ {' r ~/ P# D% W( q/ ]
* interrupt. Note: this must take account of any unprocessed
* G- l9 D% ]9 `1 N * timer interrupt which may be pending.
, L( q1 z6 J3 v, v */
$ j; w7 |% f! y! pstruct sys_timer {7 P* i7 L0 g/ Y
struct sys_device dev;; c2 F( j/ e) \; h% v
void (*init)(void);! q+ Z( ~( Q1 m, x
void (*suspend)(void);# d J. \: d6 l* v ^4 a& _
void (*resume)(void);
5 D w7 S% y9 z |#ifndef CONFIG_GENERIC_TIME
1 h! I, O3 N7 L/ P7 n unsigned long (*offset)(void);
1 Q, B0 Z! p1 x. V% d% ?8 ?3 E) Z#endif
, u& U7 q- H% L/ C7 L) l};2 y. f2 {3 E# N
% C# Z0 L/ v' [6 A( [- G/ U- tS3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。
( b" ?, B5 W# U: Sstruct sys_timer s3c24xx_timer = {
: z. I# {0 _* ^ .init = s3c2410_timer_init,
8 K( i4 u( v- w" ^ .offset = s3c2410_gettimeoffset,
# X8 _% g$ Z; Q! M .resume = s3c2410_timer_setup8 M, ?7 U# o$ |
};
4 P% \8 ]; D* @$ W
6 C8 s- a5 i3 w) f0 G" l( l. ^0 J如何将该定时器告知内核呢?
/ U) z9 ?& ^5 |+ k- T' x在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏
7 V+ k, e w9 A' R" B L
4 O+ G8 Z: f4 t) J+ M s& xMACHINE_START(S3C2440, "SMDK2440")
0 ~+ ^7 s% P: } Q r /* Maintainer: Ben Dooks <ben@fluff.org> */
1 D$ s6 n: ]. |& E) I .phys_io = S3C2410_PA_UART,
* |" G" p$ x) G8 ? .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
' a9 n1 ?& X" k! m. R .boot_params = S3C2410_SDRAM_PA + 0x100,! X) D7 e5 B4 r, x" V9 _" ~
% _, h, e% x6 s- T .init_irq = s3c24xx_init_irq,. F+ J7 a: k' d9 z4 t% A
.map_io = smdk2440_map_io,% A2 Z! z* z7 Z( n
.init_machine = smdk2440_machine_init,% g* I; b0 V! |: f
.timer = &s3c24xx_timer,$ b' W6 b! u# r/ D
MACHINE_END5 ^% N( `& T9 H
& k. b& k/ b I# t7 l
该宏用于初始化结构体struct machine_desc,结构体成员如下:6 S, [" I# B' w U4 d" L* h
struct machine_desc {$ y) c: L3 E9 e/ i1 `6 S# f4 K7 X0 T/ d' ~
/*
9 | g! v7 P: ]4 m * Note! The first four elements are used
8 H/ p h, t3 O+ Q4 J- ] * by assembler code in head.S, head-common.S
3 j, X `& U. \% K* Z K */
* D! y; ?2 S4 _. ~: b unsigned int nr; /* architecture number */
8 Y# R( i/ s7 ]9 M unsigned int phys_io; /* start of physical io */. A/ y+ i, R5 e' l
unsigned int io_pg_offst; /* byte offset for io 2 C6 d3 b* c U& E6 t3 S1 d8 `
* page tabe entry */
; g% p# o7 S% \: k3 E
2 n9 V: }7 }' f; K+ D4 K const char *name; /* architecture name */
- Z6 s, G1 v" F5 M unsigned long boot_params; /* tagged list */
' ~ K Y7 P/ f$ Y5 x' ? " ^+ G- \+ j0 G
unsigned int video_start; /* start of video RAM */# L: d: j+ ~" T7 C
unsigned int video_end; /* end of video RAM */
1 h1 T! f0 u A4 l! N
6 V5 d; _( W/ q$ K; A- x unsigned int reserve_lp0 :1; /* never has lp0 */
, _7 V9 z, q3 K; F6 a* l unsigned int reserve_lp1 :1; /* never has lp1 */
% d/ ?4 S, U$ l& w# E unsigned int reserve_lp2 :1; /* never has lp2 */
. }" B) F% {$ @' i unsigned int soft_reboot :1; /* soft reboot */
; K. R& j- |: `* Q4 b! _$ d) r5 B, b void (*fixup)(struct machine_desc *,% ] L7 u) O; O* ]
struct tag *, char **,
3 ^% d, W- w8 j6 ?. r struct meminfo *);( o0 y& j5 ?7 P7 y, A
void (*map_io)(void);/* IO mapping function */1 G& R9 H6 K3 G
void (*init_irq)(void);( J5 t7 g+ O6 _1 ]' M. M2 F! z- {
struct sys_timer *timer; /* system tick timer */: ?, b" U+ q' [" F
void (*init_machine)(void);0 e; a3 h" E5 T1 q
};
* \8 |8 e/ `& o" E
# w t6 x, i% v, \6 Z% L在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。: t. U8 k8 q& t) s [! A
接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
# Q) `. ]1 [8 m# \6 O8 e3 ]
5 H* {- U u& t! f5 v" [ system_timer = mdesc->timer;# a" t& n6 V/ _* P z( V3 U+ H9 F
" s1 p6 j }1 c4 P- x1 s
mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。2 _ W; c. p( }/ D1 |: m
; ~ C9 M$ `: Z0 u i+ j, X" M" J, H
最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:
* c0 x' I( a- O" q& N
5 ?( a6 h8 S3 h" X* I9 ]start_kernel ()--> time_init() --> system_timer->init()% C) ~. d+ y3 }: q
0 v5 }& ^# k" [& f) J/ c/ mtime_init -函数位于linux/arch/arm/kernel/time.c。
) I$ |% ]: V' s/ w
- J8 D2 Q+ X0 T. ?* h( v* `! H& b
1 D! ^+ F) Y) E0 D
& n2 ~, v+ b9 }3 ^: _. {8 D) f
H6 x/ s( v: W1 N3 P) A8 O8 [5 l. x8 |% a6 w( h/ ?8 ]/ o
+ h) N, e m' _
5 _- ]( t* G$ V
|
|