微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux静态映射分析

ARM Linux静态映射分析

时间:07-25 来源:互联网 点击:

ables */

iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));

……

}

iotable_init内核提供,定义如下:

/*

* Create the architecture specific mappings

*/

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

{

int i;

for (i = 0; i nr; i++)

create_mapping(io_desc + i);

}

由上知道,smdk2410_map_io最终调用iotable_init建立映射表。

iotable_init函数的参数有两个:一个是map_desc类型的结构体,另一个是该结构体的数量nr。这里最关键的就是struct map_desc。map_desc结构体定义如下:

/* include/asm-arm/mach/map.h */

struct map_desc {

unsigned long virtual;

unsigned long physical;

unsigned long length;

unsigned int type;

};

create_mapping( )函数就是通过map_desc提供的信息创建线性映射表的。

这样的话我们就知道了创建I/O映射表的大致流程为:只要定义相应I/O资源的map_desc结构体,并将该结构体传给iotable_init函数执行,就可以创建相应的I/O资源到内核虚拟地址空间的映射表了。

我们来看看s3c2410是怎么定义map_desc结构体的(即上面iotable_init()函数内的s3c_iodesc)。

[arch/arm/mach-s3c2410/CPU.c]

/* minimal IO mapping */

static struct map_desc s3c_iodesc[] __initdata = {

IODESC_ENT(GPIO),

IODESC_ENT(IRQ),

IODESC_ENT(MEMCTRL),

IODESC_ENT(UART)

};

IODESC_ENT宏如下:

#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }

展开后等价于:

static struct map_desc s3c_iodesc[] __initdata = {

{

.virtual = S3C24XX_VA_GPIO,

.physical = S3C24XX_PA_GPIO,

.length = S3C24XX_SZ_GPIO,

.type = MT_DEVICE

},

……

};

至此,我们可以比较清晰看到GPIO被静态映射的过程,由于我们在前面的静态映射中已经做好了GPIO的映射,也就是我们写GPIO相关驱动的时候可以如下配置引脚的原因:

s3c2410_gpio_cfgpin(xxx,xxx);

其实,s3c2410_gpio_cfgpin定义如下:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)

{

void __iomem *base = S3C2410_GPIO_BASE(pin);

unsigned long mask;

unsigned long con;

unsigned long flags;

if (pin S3C2410_GPIO_BANKB) {

mask = 1 S3C2410_GPIO_OFFSET(pin);

} else {

mask = 3 S3C2410_GPIO_OFFSET(pin)*2;

}

local_irq_save(flags);

con = __raw_readl(base + 0x00);

con = ~mask;

con |= function;

__raw_writel(con, base + 0x00);

local_irq_restore(flags);

}

其中,比较关键的一个地方:

void __iomem *base = S3C2410_GPIO_BASE(pin);

这一行中,S3C2410_GPIO_BASE定义如下:

#define S3C2410_GPIO_BASE(pin) ((((pin) ~31) >> 1) + S3C24XX_VA_GPIO)

至此,GPIO的静态映射就看得很明白了。

下面来看其他外设的静态映射:

在s3c24xx_init_io()函数中,除了iotable_init()以为,还会在最后调用,

(CPU->map_io)(mach_desc, size);

而CPU的这个map_io在arch/arm/mach-s3c2410/cpu.c里面定义如下:

static struct cpu_table cpu_ids[] __initdata = {

{

.idcode = 0x32410000,

.idmask = 0xffffffff,

.map_io = s3c2410_map_io,

.init_clocks = s3c2410_init_clocks,

.init_uarts = s3c2410_init_uarts,

.init = s3c2410_init,

.name = name_s3c2410

},

...

}

再查看s3c2410_map_io(),函数代码如下:

void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)

{

/* register our io-tables */

iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));

iotable_init(mach_desc, mach_size);

}

接下来看结构s3c2410_iodesc [arch/arm/mach-s3c2410/s3c2410.c],代码如下,

/* Initial IO mappings */

static struct map_desc s3c2410_iodesc[] __initdata = {

IODESC_ENT(USBHOST),

IODESC_ENT(USBDEV),

IODESC_ENT(CLKPWR),

IODESC_ENT(LCD),

IODESC_ENT(TIMER),

IODESC_ENT(ADC),

IODESC_ENT(WATCHDOG),

};

赫然发现IODESC_ENT(TIMER)这一行,结合之前GPIO的类似分析,IODESC_ENT宏如下:

#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }

至此,TIMER, USBHOST,USBDEV,lcd,adc,watchdog等的静态映射都看得很明白了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top