需要了解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、黄晓明陆川的前女友,因《延禧攻略》翻红,如今37岁依然单身!3536
  2. 2、《爱神》3月8日浪漫上映钟汉良牵手“赵女郎”3434
  3. 3、小赞的那年今日对自己有误解的帅哥对于自拍真的努力了290
  4. 4、《江湖论贱实录》曝主演造型郑恺变“杀马特”4593
  5. 5、《动物世界》同名主题曲MV李宇春暌违三年再度献唱热血澎湃2268
  6. 6、“女追男”的4部甜宠剧,胡一天、杨紫各一部,错过一部可惜了!421
  7. 7、蹭双十一热度,拿“黄药师”做噱头的烂片,5天票房才131万2493
  8. 8、司藤CP从戏里走到戏外,景甜张彬彬好像一对新人,网友:想随份子4919
  9. 9、《请叫我总监》:林更新终于演霸总了,女主是她,最萌身高差1666
  10. 10、周扬青罕见炫男友!晒牵手视频示爱罗志祥,网友:感动哭了3875
全部评论(0)
我也有话说
0
收藏
点赞
顶部