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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x

/ e. Z  J! G& {# r1 ^! k* p内核版本2.6.30+ I9 L3 {7 v9 }) b8 U- p7 P

! K. }2 G# y# FCPU:S3C2440
6 G0 k& S; n3 k, f
2 H1 e, {' _) V! ~' X6 U& u0 g8 D; W( p4 r+ x/ ?

. n; q  X. H  @- r( q6 D5 |本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。
6 t  R  j( e0 }% ?7 q0 c
1 U8 D0 ]) ]  m1 q2 W5 Y7 f  G
7 M0 l- X( G: {2 }+ M$ ^
1 J: I1 a- _0 _ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。
' ]$ [  D: _# n4 g7 k4 o* u$ T# b! z2 t2 `9 f
/*
6 O9 i- b* U. h5 t8 `2 ? * This is our kernel timer structure.
8 Q/ D# ^9 F! q *
! X# a! f. Y- b$ T# i * - init
- Q0 B; z4 K" [' M *   Initialise the kernels jiffy timer source, claim interrupt2 q- ?' o2 T( {! V
*   using setup_irq.  This is called early on during initialisation2 {- J6 I1 a  F: ^" P7 v1 s
*   while interrupts are still disabled on the local CPU.- G# Q0 q9 K& i: `$ D! Z" C
* - suspend' w- i: A% }; N7 g$ W" L
*   Suspend the kernel jiffy timer source, if necessary.  This& m, K5 y; Q- L0 I; C. E
*   is called with interrupts disabled, after all normal devices
6 \! p  J$ ?# ^3 A% d# H5 n *   have been suspended.  If no action is required, set this to
5 \4 L  `; h' t0 s# k. h *   NULL.
. R+ A+ i* j9 y * - resume5 i7 }' j; i) w
*   Resume the kernel jiffy timer source, if necessary.  This+ k  t; Y% P" k# W
*   is called with interrupts disabled before any normal devices
9 V8 F" |1 [! q. H# M) } *   are resumed.  If no action is required, set this to NULL.
& ?6 }& b6 D4 @5 [- ^& x* D% h+ I7 d * - offset& K0 A9 d* k! X, f1 r8 P
*   Return the timer offset in microseconds since the last timer: e3 P  g: U; Y5 ~" n' P5 |
*   interrupt.  Note: this must take account of any unprocessed1 l- L$ X1 Z' f* V
*   timer interrupt which may be pending.7 e- [4 m2 s3 T: F' m' [6 p
*/4 v/ S  _# v' n
struct sys_timer {+ I( z' J. Y: B1 U# [+ U- A
        struct sys_device        dev;5 u& F7 Z2 w4 U+ H: S
        void                        (*init)(void);
, E. o- F+ J# R0 r        void                        (*suspend)(void);
& q: U* {. d7 ~! ?! p2 m        void                        (*resume)(void);
& p2 w" ~9 `$ e5 T#ifndef CONFIG_GENERIC_TIME, F. n- g- x- w) i' c
        unsigned long                (*offset)(void);
: C, ]) u; Z% y* c8 h  F#endif
+ F3 ?5 {1 x$ A* o8 p};! X1 Q, h) k7 A# o" a, {

/ j8 k% x7 X, N% aS3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。; R  C( ^+ K9 b7 _% ]& b, y. s
struct sys_timer s3c24xx_timer = {
. E  T+ V  C- n, o    .init        = s3c2410_timer_init,
* O  Z- x# V* |2 c; L    .offset        = s3c2410_gettimeoffset,1 d$ g6 }; t( V' ^
    .resume        = s3c2410_timer_setup
$ ?0 P# \( |8 i- ?& C. x! q! ~};
/ S2 t/ g' u1 o, Q; F5 c( _8 `, _$ e" f5 W3 D
如何将该定时器告知内核呢?
: [  Q8 A+ S7 m2 d, N在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏
/ h3 f4 c: J9 X) x9 V0 y7 r$ ]; k
MACHINE_START(S3C2440, "SMDK2440")3 D9 G; F' g- D+ m& y2 H! H
        /* Maintainer: Ben Dooks <ben@fluff.org> */9 n  f0 f" [3 p( f, i
        .phys_io        = S3C2410_PA_UART,* q9 t) }0 r* Y/ |6 O; T& y4 ?4 P" e
        .io_pg_offst        = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,1 z: p% `- d8 u4 b1 }1 F6 v& W
        .boot_params        = S3C2410_SDRAM_PA + 0x100,
1 Q9 i# P. I# t. A1 I7 j4 h6 U
5 A2 H: R0 \2 {7 ~( H6 q        .init_irq        = s3c24xx_init_irq,
) o( T/ |2 ?3 y, R7 ]9 X, u        .map_io                = smdk2440_map_io,, h; ~! {3 b% M& H
        .init_machine        = smdk2440_machine_init,: j! Q% Z4 _+ A
        .timer                = &s3c24xx_timer,
$ v0 T' ?- q) U( `+ j2 ]MACHINE_END
  g7 |* Z3 v% N- Y" d" [& ^
( U) K, r. l# y该宏用于初始化结构体struct machine_desc,结构体成员如下:
" e% x# Z2 e: estruct machine_desc {
7 E+ j) P& ~+ J4 G7 N& P" y        /*! G) a6 I! P# e( s# j
         * Note! The first four elements are used
3 c( t- d' a. O3 O! {) N; l% e         * by assembler code in head.S, head-common.S" t( P% T7 y% R; ]- w7 \+ m
         */, M  w! o, i2 F0 w( I3 ^! _
        unsigned int                nr;                /* architecture number        */
3 ^+ h% l; w/ ~  X% |        unsigned int                phys_io;        /* start of physical io        */
8 d8 j) ^/ {, U3 {0 z% a: i; E        unsigned int                io_pg_offst;        /* byte offset for io
- A$ `+ r! M& V6 l- l7 ?; Z                                                 * page tabe entry        */
/ Z- v: Q: C% @0 G2 T
: o7 j  T! c) e: x        const char                *name;                /* architecture name        */
/ p( T; `6 Y1 a4 B% u7 y        unsigned long                boot_params;        /* tagged list                */9 E$ `1 L  W" j5 U# f
( p; C& q- |: a2 V+ t
        unsigned int                video_start;        /* start of video RAM        */& B/ E; Q- t% E2 b
        unsigned int                video_end;        /* end of video RAM        */
% S1 e7 C& B# R" O$ S1 }
1 X6 V; h! E/ U- y' Z" D        unsigned int                reserve_lp0 :1;        /* never has lp0        */
3 V1 n, P1 }7 O1 m8 G        unsigned int                reserve_lp1 :1;        /* never has lp1        */
* s' |: \' c( ?3 r4 G1 z  `        unsigned int                reserve_lp2 :1;        /* never has lp2        */
: d' o7 z9 a/ h5 h        unsigned int                soft_reboot :1;        /* soft reboot                */9 `  j/ \6 x. t0 q3 f, R( x" A
        void                        (*fixup)(struct machine_desc *,
' j- x' |- l7 i. }                                         struct tag *, char **,
% f( X( H9 R1 N8 m" {                                         struct meminfo *);0 b. X0 f& E( g3 ]8 ^4 o5 m. s& x' x
        void                        (*map_io)(void);/* IO mapping function        */' y2 y8 f: F# x* q4 {+ c
        void                        (*init_irq)(void);, R9 y7 O1 }  @7 s" ]5 d
        struct sys_timer        *timer;                /* system tick timer        */
' Q& a% r* ]# M9 _  h* N. G$ V        void                        (*init_machine)(void);
; h" ^' c5 N' n5 ^- M};  r& X: h+ `4 [. k  S7 {

  y) z* a, m( R" t, z' J' [在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。
: E0 p6 [2 a: y1 I5 U) `; o# ?. \* N8 L接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:
. n$ N3 y; Z- Y8 X! O8 y$ N8 {! E1 z( H# `
    system_timer = mdesc->timer;
, _6 f( t# i8 l0 [1 K9 w1 `  l# ]+ H9 y( N7 X
mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。
0 h0 c3 @3 H1 k# z) `1 n4 G2 r8 I
# w( u( y" t. r3 z最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:! x; t* o3 u( o$ g4 k6 ^$ k
) ]% d& y5 G/ N2 N# {, L9 a/ m: v
start_kernel ()-->  time_init()  --> system_timer->init()
8 ]& y: a2 m+ Q0 s
- a: O$ l" i8 I/ q' Wtime_init  -函数位于linux/arch/arm/kernel/time.c。7 s9 ]2 \/ `; Z7 t5 j# u
: o" Q& ~* i1 Y( ]2 D% f

4 z, E( x% ^% J4 V. H) O; c4 ^" n5 P  U1 h- J- W
' E3 \' l$ e% [; ?
* g6 `/ h8 W# p- H

! }; g( i# F8 I- I1 _6 f. _: V: M0 w) T& T0 {* f3 {
  • 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 23:05 , Processed in 0.156250 second(s), 24 queries , Gzip On.

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

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

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