找回密码
 注册
关于网站域名变更的通知
查看: 186|回复: 1
打印 上一主题 下一主题

了解一下Linux系统的节拍定时器吧(system tick timer)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-6-12 11:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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
  • TA的每日心情
    慵懒
    2020-6-13 15:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-6-12 13:13 | 只看该作者
    节拍定时器
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-25 16:43 , Processed in 0.171875 second(s), 24 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表