关于节拍定时器

ARM 203浏览


https://blog.csdn.net/yj4231/article/details/8464307

本文主要说明节拍定时器是如何添加到内核中的,不对定时器实现进行说明。

ARM 平台的节拍定时器对象使用sys_timer来表示,该结构体位于arch/arm/include/asm/mach/time.h。

/*
 * This is our kernel timer structure.
 *
 * - init
 *   Initialise the kernels jiffy timer source, claim interrupt
 *   using setup_irq.  This is called early on during initialisation
 *   while interrupts are still disabled on the local CPU.
 * - suspend
 *   Suspend the kernel jiffy timer source, if necessary.  This
 *   is called with interrupts disabled, after all normal devices
 *   have been suspended.  If no action is required, set this to
 *   NULL.
 * - resume
 *   Resume the kernel jiffy timer source, if necessary.  This
 *   is called with interrupts disabled before any normal devices
 *   are resumed.  If no action is required, set this to NULL.
 * - offset
 *   Return the timer offset in microseconds since the last timer
 *   interrupt.  Note: this must take account of any unprocessed
 *   timer interrupt which may be pending.
 */
struct sys_timer {
    struct sys_device    dev;
    void            (*init)(void);
    void            (*suspend)(void);
    void            (*resume)(void);
#ifndef CONFIG_GENERIC_TIME
    unsigned long        (*offset)(void);
#endif
};

S3C2440的sys_timer的定义在linux/arch/arm/plat-s3c24xx/time.c中,给出的三个方法也在该文件中定义。

struct sys_timer s3c24xx_timer = {
    .init        = s3c2410_timer_init,
    .offset        = s3c2410_gettimeoffset,
    .resume        = s3c2410_timer_setup
};

如何将该定时器告知内核呢?

在linux/arch/arm/mach-s3c2440/mach-smdk2440.c的最后使用了宏

MACHINE_START(S3C2440, "SMDK2440")
    /* Maintainer: Ben Dooks <ben@fluff.org> */
    .phys_io    = S3C2410_PA_UART,
    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S3C2410_SDRAM_PA + 0x100,

    .init_irq    = s3c24xx_init_irq,
    .map_io        = smdk2440_map_io,
    .init_machine    = smdk2440_machine_init,
    .timer        = &s3c24xx_timer,
MACHINE_END

该宏用于初始化结构体struct machine_desc,结构体成员如下:

struct machine_desc {
    /*
     * Note! The first four elements are used
     * by assembler code in head.S, head-common.S
     */
    unsigned int        nr;        /* architecture number    */
    unsigned int        phys_io;    /* start of physical io    */
    unsigned int        io_pg_offst;    /* byte offset for io
                         * page tabe entry    */

    const char        *name;        /* architecture name    */
    unsigned long        boot_params;    /* tagged list        */

    unsigned int        video_start;    /* start of video RAM    */
    unsigned int        video_end;    /* end of video RAM    */

    unsigned int        reserve_lp0 :1;    /* never has lp0    */
    unsigned int        reserve_lp1 :1;    /* never has lp1    */
    unsigned int        reserve_lp2 :1;    /* never has lp2    */
    unsigned int        soft_reboot :1;    /* soft reboot        */
    void            (*fixup)(struct machine_desc *,
                     struct tag *, char **,
                     struct meminfo *);
    void            (*map_io)(void);/* IO mapping function    */
    void            (*init_irq)(void);
    struct sys_timer    *timer;        /* system tick timer    */
    void            (*init_machine)(void);
};

在这里我们看到了timer指针。通过该宏将timer指针指向了s3c24xx_timer。

接着,再看linux/arch/arm/kernel/setup.c中的setup_arch函数,该函数中执行了下面这话:

    system_timer = mdesc->timer;

mdesc->timer即为上面宏所给出的s3c24xx_timer,而system_timer为全局变量。通过该全局变量就可使用节拍定时器。

最后,我们看下节拍定时器的init方法何时被调用,调用顺序如下:

start_kernel ()–> time_init() --> system_timer->init()

time_init -函数位于linux/arch/arm/kernel/time.c。