基于S3C2410-ARM-Linux静态映射分析

来源:互联网 发布:西安seo缑阳建 编辑:程序博客网 时间:2024/04/30 01:17

s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);   

 
   我们可以这样控制外设寄存器,想过它怎么实现的吗?
 
   首先分析下 struct machine_desc  (include/asm-arm/Mach/Arch.h)
这是一个非常重要的结构体,内核通过 machine_desc  来控制体系架构相关部分的初始化,包括map_io,init_irq,init_machine,pthys_io,timer等
   

struct machine_desc {
    
/*
     * Note! The first five elements are used
     * by assembler code in head-armv.S
     */

    unsigned int        nr;        /* architecture number    */
    unsigned int        phys_ram;    /* start of physical ram */
    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);
};

   那我们怎么创建自己的machine_desc呢?
    内核给我们提供了一个宏:
 

#define MACHINE_START(_type,_name)        /
const struct machine_desc __mach_desc_##_type    /
 __attribute__((__section__(".arch.info.init"))) = {    /
    .nr        = MACH_TYPE_##_type,    /
    .name        = _name,
#define MACHINE_END                /
};


这样我们就可以定义自己的machine_desc了

MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                 * to SMDK2410 */

    /* Maintainer: Jonas Dietsche */
    .phys_ram    = S3C2410_SDRAM_PA,
    .phys_io    = S3C2410_PA_UART,
    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S3C2410_SDRAM_PA + 0x100,
    .map_io        = smdk2410_map_io,
    .init_irq    = smdk2410_init_irq,
     .init_machine = sdmk2410_init,
    .timer        = &s3c24xx_timer,
MACHINE_END

这里我们创建了 machine_desc,并给其中一些成员赋了值,这相当于是内核给我们提供的编程接口,这样就可以调用自己的函数了。

这其中map_io 在 setup_arch 中调用调用,我们跟进去会发现:

smdk2410_map_io-->s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc))->iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)) 看到:

void __init iotable_init(struct map_desc *io_desc, int nr)
{
    int i;
    for (i = 0; i < nr; i++)
        create_mapping(io_desc + i);
}

就是在这里调用create_mapping()创建的页表,这里的第一个参数,map_desc 定义如下:

struct map_desc {
    unsigned long virtual;
    unsigned long physical;
    unsigned long length;
    unsigned int type;
};

create_mapping()就是通过这个结构体创建的映射表,这样我们可以通过创建 map_desc 然后传给这个函数就可以创建相应的 虚拟地址-->物理地址 映射.

在 inlcude/asm-arch/Arch-s3c2410/Map.h

定义了每一种资源用于 map_desc 变量的宏定义,如:

/* MMC controller - available on the S3C2400 */
#define S3C2400_VA_MMC      S3C2400_ADDR(0x00700000)
#define S3C2400_PA_MMC      (0x15A00000)
#define S3C2400_SZ_MMC      SZ_1M

/* UARTs */
#define S3C24XX_VA_UART     S3C2410_ADDR(0x00800000)
#define S3C2400_PA_UART     (0x15000000)
#define S3C2410_PA_UART     (0x50000000)
#define S3C24XX_SZ_UART     SZ_1M

/* Timers */
#define S3C24XX_VA_TIMER S3C2410_ADDR(0x00900000)
#define S3C2400_PA_TIMER (0x15100000)
#define S3C2410_PA_TIMER (0x51000000)
#define S3C24XX_SZ_TIMER SZ_1M

 

然后针对具体的某个外设,有具体寄存器的定义,如:

include/asm/arch-s3c2410/regs-timer.h
 

#ifndef __ASM_ARCH_REGS_TIMER_H
#define __ASM_ARCH_REGS_TIMER_H "$Id: timer.h,v 1.4 2003/05/06 19:30:50 ben Exp $"

#define S3C2410_TIMERREG(x) (S3C24XX_VA_TIMER + (x))
#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))

#define S3C2410_TCFG0     S3C2410_TIMERREG(0x00)
#define S3C2410_TCFG1     S3C2410_TIMERREG(0x04)
#define S3C2410_TCON     S3C2410_TIMERREG(0x08)

#define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
#define S3C2410_TCFG_PRESCALER1_MASK (255<<8)
#define S3C2410_TCFG_PRESCALER1_SHIFT (8)
#define S3C2410_TCFG_DEADZONE_MASK (255<<16)
#define S3C2410_TCFG_DEADZONE_SHIFT (16)
.........................

我分析的只是一个大概,具体请参考:ARM Linux静态映射分析--易松华

http://www.docin.com/p-63183730.html

原创粉丝点击