S5PV210静态映射表的构建过程

注:分析的三星官方的内核。
一、板子启动相关
1.首先得明白一般与板子相关的启动初始化都在mach-xxx.c文件。因为静态映射表我们主要关注的是板子的GPIO,而GPIO也属于板子启动必须初始化的部分,所以我们要找的文件就是/kernel/arch/arm/mach-s5pv210/mach-smdkc110.c文件。
2.熟悉内核的人都知道板子的启动相关初始化都在一个结构体当中。
(1)相关的代码片段

#ifdef CONFIG_MACH_SMDKC110
MACHINE_START(SMDKC110, "SMDKC110")
#elif CONFIG_MACH_SMDKV210
MACHINE_START(SMDKV210, "SMDKV210")
#endif
    /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
    .phys_io    = S3C_PA_UART & 0xfff00000,
    .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S5P_PA_SDRAM + 0x100,
    //.fixup        = smdkv210_fixup,
    .init_irq   = s5pv210_init_irq,
    .map_io     = smdkc110_map_io,
    .init_machine   = smdkc110_machine_init,
    .timer      = &s5p_systimer,
MACHINE_END

(2)MACHINE_START和MACHINE_END是一个宏定义,主要是用来定一个结构体变量的,并且填充其内部一部分变量

#define MACHINE_START(_type,_name)          \
static const struct machine_desc __mach_desc_##_type    \
 __used                         \
 //__attribute__是给这个结构体设置一个段属性,当内核链接时会根据段的顺序(具体的段顺序在链接脚本里面指定)。来链接生成zImage。
 __attribute__((__section__(".arch.info.init"))) = {    \
    .nr     = MACH_TYPE_##_type,        \
    .name       = _name,
#define MACHINE_END             };

(3)因为我们分析的S5PV210,所以我们肯定在内核中定义了CONFIG_MACH_SMDKV210,所以上面的宏,展开后就是

static const struct machine_desc __mach_desc_SMDKV210   \
 __used                         \
 __attribute__((__section__(".arch.info.init"))) = {    \
    .nr     = MACH_TYPE_SMDKV210,       \
    .name       = "SMDKV210",
    .phys_io    = S3C_PA_UART & 0xfff00000,
    .io_pg_offst    = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
    .boot_params    = S5P_PA_SDRAM + 0x100,
    //.fixup        = smdkv210_fixup,
    .init_irq   = s5pv210_init_irq,
    .map_io     = smdkc110_map_io,
    .init_machine   = smdkc110_machine_init,
    .timer      = &s5p_systimer,
};

3.(聪明点的人一眼就能看出)smdkc110_map_io函数就是静态映射表的构建函数。因为名字很显眼嘛。好进入函数,下面有一个叫s5p_init_io(NULL, 0, S5P_VA_CHIPID)的函数。继续追,关键的代码就在这个函数里面了。

二、s5p_init_io函数分析
1.s5p_iodesc分析
(1)map_desc结构体在/kernel/arch/arm/include/asm/mach/map.h里面定义
struct map_desc {
//虚拟地址
unsigned long virtual;
//物理地址
unsigned long pfn;
unsigned long length;
unsigned int type;
};
(2)可见定义了一个map_desc类型的数组,里面包含了对应模块的映射信息,每一个元素代表一个映射关系(虚拟地址到物理地址)。

static struct map_desc s5p_iodesc[] __initdata = {
    {
        .virtual    = (unsigned long)S5P_VA_CHIPID,
        .pfn        = __phys_to_pfn(S5P_PA_CHIPID),
        .length     = SZ_4K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)S3C_VA_SYS,
        .pfn        = __phys_to_pfn(S5P_PA_SYSCON),
        .length     = SZ_64K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)S3C_VA_UART,
        .pfn        = __phys_to_pfn(S3C_PA_UART),
        .length     = SZ_4K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)VA_VIC0,
        .pfn        = __phys_to_pfn(S5P_PA_VIC0),
        .length     = SZ_16K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)VA_VIC1,
        .pfn        = __phys_to_pfn(S5P_PA_VIC1),
        .length     = SZ_16K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)S3C_VA_TIMER,
        .pfn        = __phys_to_pfn(S5P_PA_TIMER),
        .length     = SZ_16K,
        .type       = MT_DEVICE,
    }, {
        .virtual    = (unsigned long)S5P_VA_GPIO,
        .pfn        = __phys_to_pfn(S5P_PA_GPIO),
        .length     = SZ_4K,
        .type       = MT_DEVICE,
    },
};

(3)而这个结构体被iotable_init函数所使用,里面实际调用了create_mapping函数。

void __init iotable_init(struct map_desc *io_desc, int nr)
{
    int i;

    for (i = 0; i < nr; i++)
        create_mapping(io_desc + i);
}

(4)create_mapping函数负责将这个结构体转换成MMU能够识别的页表映射关系,这样开机之后就能直接使用虚拟地址来访问对应的物理地址。

2.而s5p_iodesc结构里面的S5P_VA_CHIPID、S3C_VA_SYS类似的这些宏定义是三星出场针对不同的CPU来定义的。
(1)主映射表位于:arch/arm/plat-s5p/include/plat/map-s5p.h
(2)虚拟地址基地址定义在:arch/arm/plat-samsung/include/plat/map-base.h

#define S3C_ADDR_BASE   (0xFD000000)

三、创建好映射表之后
1.在内核启动的时候这个表就会被建立。
2.建立的过程函数,就是一条线路。自己分析。(每一个TAB键就是一个函数层次关系)

start_kernel
    setup_arch
        paging_init
            devicemaps_init
                if (mdesc->map_io)
                    mdesc->map_io();

能力有限,我也是学习者,只能分析到这个程度,大概了解。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值