EDA365电子论坛网

标题: 了解一下Linux系统的节拍定时器吧(system tick timer) [打印本页]

作者: thinkfunny    时间: 2020-6-12 11:05
标题: 了解一下Linux系统的节拍定时器吧(system tick timer)

& t* X$ F  N# T1 r/ J0 r4 \内核版本2.6.30
* Z7 J, W/ X/ v6 P# _' v* |( Y, e8 ]+ O  p* X5 u4 K9 [
CPU:S3C24405 R$ D0 M& d: Y0 }! R) `
4 J! s; ^0 J% L$ k. T- D

$ U( e: I. `( K: U2 y2 m
8 j4 u$ r- z( @: m  l本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。( W$ y* ~( T( e, N. ^, {) |# p9 ?
0 I3 T; L* Y( M/ K; u* d

4 [9 o2 }1 V, _9 h6 V2 [, o, z# }/ Q. M! u
ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。
8 O$ A' O8 @3 Z/ a$ B9 k
! o6 I! V% G9 p# k; l. E, }/*
& \& M  U3 e; b! W9 X7 p * This is our kernel timer structure.
0 T" ]. |. Z4 N% F. N7 ^ ** w3 O9 T' q+ f
* - init
3 l4 p2 l( P+ v& i& ]% J8 i *   Initialise the kernels jiffy timer source, claim interrupt) |, ], @$ u7 R! W7 n
*   using setup_irq.  This is called early on during initialisation; C8 P, e, |( B4 r2 V& b* h* @
*   while interrupts are still disabled on the local CPU.
  i# w+ C8 e# n! O" L8 t * - suspend
7 Z/ U" H! o' i2 k: U *   Suspend the kernel jiffy timer source, if necessary.  This, r" l7 Z3 T( L& J; ~. e
*   is called with interrupts disabled, after all normal devices
" ?5 i/ ?& K3 |( T' C0 d: A. { *   have been suspended.  If no action is required, set this to% Y; j& V8 V7 ?3 O! i1 ^. N
*   NULL.
: }( O8 Z! ^# Z: Q( F7 S' M. V * - resume
( z' H  }( f# @- O6 Z *   Resume the kernel jiffy timer source, if necessary.  This
4 Z4 ^( K! x; Q  l2 Z *   is called with interrupts disabled before any normal devices$ z3 X) q- f# x* e: I# Y
*   are resumed.  If no action is required, set this to NULL.9 p$ _# X" w1 w8 u
* - offset8 i% b6 w5 L3 L
*   Return the timer offset in microseconds since the last timer# W6 N* \) N# a1 e% o% m  {  R; u
*   interrupt.  Note: this must take account of any unprocessed
# ]" V9 n$ h& ^- {8 f *   timer interrupt which may be pending.1 h" p- e8 @5 ~) H. c
*/1 z# @3 J% b# s6 R- a$ X
struct sys_timer {
4 @9 O& u8 |( u1 M8 }* [. c        struct sys_device        dev;
8 C% o- c+ e6 o. s+ o        void                        (*init)(void);
. C* V/ P% ^6 d8 ~& J        void                        (*suspend)(void);
0 E: @! m  g+ X' B9 e% ]        void                        (*resume)(void);: T8 l1 _6 f! b! n6 r$ T5 P
#ifndef CONFIG_GENERIC_TIME  m, {# D! C, X- @9 p3 v
        unsigned long                (*offset)(void);- w! U2 V% M2 H# S9 d- J  N' K4 F3 Y
#endif) Y. u. l9 h7 o* }* W0 |
};
+ @" i4 ?6 H, d. a* _5 a3 {" m) G7 W/ ?0 |6 P' i9 O+ w
S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。
: u2 t( V9 m+ W8 x7 a2 k  ~: `struct sys_timer s3c24xx_timer = {
% L/ ^; h4 d5 }# y# Y% u    .init        = s3c2410_timer_init," x* |4 b7 O6 t- N
    .offset        = s3c2410_gettimeoffset,
; W* c, S  L; }( S    .resume        = s3c2410_timer_setup! y5 i7 f5 J; T" j
};
+ S: X$ L9 E. x. }. U% r2 Z2 H* {) M* \& k7 v0 N; U
如何将该定时器告知内核呢?
2 q# ]% g* k" V* S7 _; ]在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏( h. T3 W4 F/ I) t: U. H# Q

( U' F* T0 m( P+ mMACHINE_START(S3C2440, "SMDK2440")
( e  n4 C4 c$ I0 ?1 X        /* Maintainer: Ben Dooks <ben@fluff.org> */
* i9 o& B+ v- F        .phys_io        = S3C2410_PA_UART,& P  q/ D2 W7 Q5 E; c$ _& {
        .io_pg_offst        = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
, Y5 s( G& ?$ \# a4 o( }* c& l* u        .boot_params        = S3C2410_SDRAM_PA + 0x100,3 k; ]' U$ h# x4 s. M0 G/ G$ J7 p1 w

+ \  c  a" p: H2 w& F4 P- |        .init_irq        = s3c24xx_init_irq,% S" i$ R! V7 W4 Y4 {
        .map_io                = smdk2440_map_io,8 l3 n4 P7 m: L9 y+ R
        .init_machine        = smdk2440_machine_init,
& o# G  h8 G& b0 G; `+ V        .timer                = &s3c24xx_timer,
4 r" i6 R" J9 K- p) M2 FMACHINE_END, l. p  m; w  T) M
7 G$ B+ W7 f" u  ?! H
该宏用于初始化结构体struct machine_desc,结构体成员如下:
& N5 \+ u# W5 N8 n) D% Istruct machine_desc {
# W3 M, M' y. V( T+ \) H& m        /*
0 a) H! W# L% t1 I! u6 V         * Note! The first four elements are used/ k$ ]4 R/ o6 m( V2 H
         * by assembler code in head.S, head-common.S
/ \" w" Q: a; v2 \) u         */
" Y3 o: t1 l! V+ l' K        unsigned int                nr;                /* architecture number        */3 T" A6 l& x, W( ~  o  a' {
        unsigned int                phys_io;        /* start of physical io        */% w: f* i7 K  M& |3 e9 z6 T# V
        unsigned int                io_pg_offst;        /* byte offset for io
7 \$ O- }  l6 I3 b. @2 S4 M6 p# Q                                                 * page tabe entry        */' s/ t; y2 P2 y9 A) m8 D

# S3 h) P! a9 r8 [4 x        const char                *name;                /* architecture name        */
5 n, {1 s  M6 {7 e" J        unsigned long                boot_params;        /* tagged list                */
1 Y" r3 G( S  e( @ 3 j; U8 `( V  O& T$ q' H4 L
        unsigned int                video_start;        /* start of video RAM        */
) m. c7 ?3 h) b  U7 S6 T  S# c6 R3 V        unsigned int                video_end;        /* end of video RAM        */
) w& Z, a8 o$ q4 I . |- o* K: ^& W- N
        unsigned int                reserve_lp0 :1;        /* never has lp0        */
) g& n4 G3 E/ h/ J. {5 w        unsigned int                reserve_lp1 :1;        /* never has lp1        */
% k$ s4 ^, M$ O/ `( y        unsigned int                reserve_lp2 :1;        /* never has lp2        */) j" O* C7 g# D6 D5 Z7 b: t! f
        unsigned int                soft_reboot :1;        /* soft reboot                */
4 b, u  V2 A: ?) ]  L# v' m5 E0 J5 g        void                        (*fixup)(struct machine_desc *,/ L$ i/ [1 j( c8 `- ]. Q. i
                                         struct tag *, char **,
6 R. r* Y1 b9 L& S" E                                         struct meminfo *);! X) E4 j# @- u4 s2 F5 {( m
        void                        (*map_io)(void);/* IO mapping function        */0 l3 ?  m# g/ q; B. T1 ~$ ^
        void                        (*init_irq)(void);
9 S% R0 |0 }5 Z. z0 U1 r        struct sys_timer        *timer;                /* system tick timer        */: M9 I) |+ A) H
        void                        (*init_machine)(void);1 g7 ~0 V% a1 U$ J* e
};+ S3 j7 l; A/ A( C6 n

- a* ^, B7 n4 m; X/ S+ Y; K在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。% u4 }6 k1 Q/ s- W
接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
" m9 K5 f! o" }' X# u
# P! V4 h' I  Q( N    system_timer = mdesc->timer;
( S5 I; ?) |4 v1 E! R2 H7 \
4 a4 ~9 E2 G* V% `7 Ymdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。( k8 S3 g- {+ Z" j+ H: W: k; B7 \( k
5 K  s- u% y/ G, n$ _! o" N2 r
最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:
* X6 P1 L4 g  t. q0 X
% G/ ~3 e. X8 P, H0 P# Vstart_kernel ()-->  time_init()  --> system_timer->init()
4 O; A  y- g' J7 p
0 @# T& B# C) ]4 _time_init  -函数位于linux/arch/arm/kernel/time.c。
0 ^0 n9 U: G$ g% R' X/ P" z  X( N9 j

8 U# N/ G  k' r* k" ?  J
8 ?3 t9 V: l# x
* k- G+ T9 l2 [. k: Y, D% l
0 H- B. X! m" s. S* P# o8 C" g. q6 @1 _5 W
! ^$ i: d4 Y7 k! m

作者: younicp    时间: 2020-6-12 13:13
节拍定时器




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2