需要了解Embededlinux的地址映射

 一、板级文件

通常会由MACHINE_START到板级文件

MACHINE_START(Chipname, "Chipname")
.atag_offset    = 0x100,
.map_io      = Chipname_map_io,
.init_early    = Chipname_init_early,
.init_irq     = Chipname_gic_init_irq,
.handle_irq   = gic_handle_irq,
.     ti   mer       = &Chipname_sys_  TI mer,
.init_machine  = Chipname_init,
.reserve     = Chipname_reserve,
.restart      = Chipname_restart,
MACHINE_END

.map_io是一个函数指针,这里指定了Chipname_map_io。函数实体为:

void __init Chipname_map_io(void)

{

...

}

二、内存映射

芯片IO口操作分为两类:

1.     寄存器   与内存统一编址,又称IO内存

2.寄存器与内存不统一编址,又称IO端口

    ARM   芯片基本上是统一编址,访问寄存器(包括系统寄存器、外设寄存器、IO口寄存器等)直接访问该地址即可。

其中     linux   支持的寄存器地址寻址方式为内存映射,即将内核内存1G的某一些地址映射给寄存器,这样操作内核虚拟内存地址就是操作寄存器。

三、映射方式

linux内核提供的映射方式有两种:

1.静态映射

使用map_desc结构体进行映射,其中map_desc结构体为:

struct map_desc {
unsigned long virtual;  //虚拟地址
unsigned long pfn;    //__phys_to_pfn(物理地址) , 就是物理页框号
unsigned long length;  //长度
unsigned int type;    //类型
};

举例,填充一个映射信息结构体,映射两块连续的地址空间,出现保留字就再映射一个,或者遇到不需要控制的地址,否则一直连续映射:

sta  TI c struct map_desc Chipname_io_desc[] __initdata = {
{
.virtual = 0xFE000000,
.pfn = __phys_to_pfn(0x10000000),
.length = 0xD0000,
.type = MT_DEVICE
},
{
.virtual = 0xFE100000,
.pfn = __phys_to_pfn(0x20000000),
.length = 0x700000,
.type = MT_DEVICE
}
};

然后调用     iot   able_init(Chipname_io_desc, ARRAY_SIZE(Chipname_io_desc));建立映射的函数

以后直接*(vola  TI le unsigned int *)0xFE000000就能使用了。

2.动态映射

驱动中手动映射某一个地址

#define ioremap(cookie,size)         __arm_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_cached(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size)       __arm_ioremap((cookie), (size), MT_DEVICE_WC)
#define iounmap               __arm_iounmap

cookie:物理地址

size:要映射的空间的大小;

返回虚拟地址

头文件io.h

以后直接*(vola  TI le unsigned int *)虚拟地址就能使用了。

扩展:

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) //include/linux/kernel.h,ARRAY_SIZE为计算数组的一维维度,计算方法为数组大小和数组单成员大小之商

#ifdef __CHECKER__
#define __must_be_array(arr) 0
#else
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) //include/linux/com     pi   ler-gcc.h

#endif

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) //include/linux/bug.h,BUILD_BUG_ON_ZERO的作用在于将返回值转化为编译错误信息。显然当内嵌函数返回值为0时,也即类型相同时,由于BUILD_BUG_ON_ZERO参数为非0而导致char[-1]而发出编译器警告。

#ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))  //include/linux/compiler.h,gcc编译器内嵌的函数,判断一个变量的类型是否为某指定的类型,假如是就返回1,否则返回0。这里通过判断指针和指针指向的第一个元素的指针是否是相同类型来判断是否为数组。
#endif

arch/arm/mm/mmu.c

void __init iotable_init(struct map_desc *io_desc, int nr)
{
struct map_desc *md;
struct vm_struct *vm;

if (!nr) return;

/*early_alloc_aligned

*

*/

vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm));

for (md = io_desc; nr; md++, nr--)

{

crea     te   _mapping(md, false);
vm->addr = (void *)(md->virtual & PAGE_MASK);
vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
vm->phys_addr = __pfn_to_phys(md->pfn);
vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
vm->flags |= VM_ARM_MTYPE(md->type);
vm->caller = iotable_init;
vm_area_add_early(vm++);
}
}




需要了解Embededlinux的地址映射_设计制作_模拟技术
15
3
0
33

相关资讯

  1. 1、《三国战纪群雄逐鹿》职业公开攻防技相爱相杀319
  2. 2、光棍节狂欢!决战沙城双11多重活动来袭4552
  3. 3、七星伙伴首揭秘《兵器少女》新版即将来袭1459
  4. 4、最萌女团空降《长生诀》古风公演新玩法3830
  5. 5、萌塔英雄iOS越狱内测今日开启体验动作塔防新定义4582
  6. 6、一生兄弟忆沙城《烈火雷霆》征战热血青春4718
  7. 7、女神降临《新世纪福音战士OL》人设原画首曝1827
  8. 8、《弹弹岛2》“战魂觉醒”劲爆来袭周年狂欢盛大开启3582
  9. 9、定档9月!《封神妲己传》预约不删测享豪礼3419
  10. 10、突破等级桎梏《新秦时明月》新版大揭秘324
全部评论(0)
我也有话说
0
收藏
点赞
顶部