ARM Linux静态映射分析
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等的静态映射都看得很明白了。
- 基于赛灵思Spartan-3A DSP的安全视频分析(02-17)
- 关于Linux操作系统的NTFS和内核分析(05-19)
- Linux 2.4.x内核软中断机制(04-06)
- 基于DSP的人脸识别系统设计(04-26)
- 3D图形芯片的算法原理分析(07-16)
- 解析:视频图像智能分析处理技术(08-08)