ARM Linux静态映射分析 - 华清远见嵌入式学院_第1页
ARM Linux静态映射分析 - 华清远见嵌入式学院_第2页
ARM Linux静态映射分析 - 华清远见嵌入式学院_第3页
ARM Linux静态映射分析 - 华清远见嵌入式学院_第4页
ARM Linux静态映射分析 - 华清远见嵌入式学院_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PAGEPAGE1ARMLinux静态映射分析-华清远见嵌入式学院在华清远见上课经过中,发现静态映射方面初学者比较难于把握和理解,下面分析一下静态映射机制的原理并通过GPIO和USB、LCD等的静态映射作为例子来说明怎样通过这种静态映射的方式访问外设资源。内核提供了一个主要的构造体structmachine_desc,这个构造体在内核移植中起到相当主要的作用,内核通过machine_desc构造体来控制系统体系架构相关部分的初始化。machine_desc构造体的成员包括了体系架构相关部分的几个主要的初始化函数,包含map_io,init_irq,init_machine以及phys_io,timer成员等。machine_desc构造体定义如下:structmachine_desc{/**Note!Thefirstfourelementsareused*byassemblercodeinhead-armv.S*/unsignedintnr;/*architecturenumber*/unsignedintphys_io;/*startofphysicalio*/unsignedintio_pg_offst;/*byteoffsetforio*pagetabeentry*/constchar*name;/*architecturename*/unsignedlong;boot_params;/*taggedlist*/unsignedintvideo_start;/*startofvideoRAM*/unsignedintvideo_end;/*endofvideoRAM*/unsignedintreserve_lp0:1;/*neverhaslp0*/unsignedintreserve_lp1:1;/*neverhaslp1*/unsignedintreserve_lp2:1;/*neverhaslp2*/unsignedintsoft_reboot:1;/*softreboot*/void(*fixup)(structmachine_desc*,structtag*,char**,structmeminfo*);void(*map_io)(void);/*IOmappingfunction*/void(*init_irq)(void);structsys_timer*timer;/*systemticktimer*/void(*init_machine)(void);};machine_desc构造体通过MACHINE_START宏来初始化,这里以s3c2410平台为例:s3c2410machine_desc构造体定义如下:/*arch/arm/mach-s3c2410/mach-smdk2410.c*/MACHINE_START(SMDK2410,SMDK2410)/*@TODO:requestanewidentifierandswitch*toSMDK2410*//*Maintainer:JonasDietsche*/.phys_io=S3C2410_PA_UART,.io_pg_offst=(((u32)S3C24XX_VA_UART)18)0xfffc,.boot_params=S3C2410_SDRAM_PA+0x100,.map_io=smdk2410_map_io,.init_irq=s3c24xx_init_irq,.init_machine=smdk2410_init,.timer=s3c24xx_timer,MACHINE_END其中的宏MACHINE_START和MACHINE_END定义如下:/**Setofmacrostodefinearchitecturefeatures.Thisisbuiltinto*atablebythelinker.*/#defineMACHINE_START(_type,_name)\conststructmachine_desc__mach_desc_##_type\__attribute__((__section__(..init)))={\.nr=MACH_TYPE_##_type,\.name=_name,#defineMACHINE_END\};其中MACH_TYPE_##_type为GCC扩展语法中的字符拼接标识,在预编译的时候会用真正的字符代替,比方我们这里就是MACH_TYPE_SMDK2410MACHINE_START的使用及各个成员函数的的放置位置以及调用经过如下:MACH_TYPE_SMDK2410这个值是目的板的类型值,定义在arch/include/asm-arm/mach-types.h内,值为193./*arch/include/asm-arm/mach-types.h*/#defineMACH_TYPE_SMDK2410193由上发现,MACHINE_START重要是定义了structmachine_desc的类型,放在section(..init),是初始化数据,其所占用的内存在内核起来之后将会被释放。这里的map_io成员即内核提供应用户的开创建立外设I/O资源到内核虚拟地址静态映射表的接口函数。map_io成员函数会在系统初始化经过中被调用,流程如下:start_kernel-setup_arch()--paging_init()中被调用structmachine_desc构造体的各个成员函数在不同时期被调用:1..init_machine在arch/arm/kernel/setup.c中被customize_machine调用,放在arch_initcall()段里面,会自动按顺序被调用〔另外博客分析,敬请关注〕。2.init_irq在start_kernel()--init_IRQ()--init_arch_irq()被调用3.map_io在setup_arch()--paging_init()被调用其他重要都在setup_arch()顶用到。用户能够在定义machine_desc构造体时指定map_io的接口函数,我们也恰是这样做的。接下来我们继续分析smdk2410_map_io的履行经过,流程如下:smdk2410_map_io-s3c24xx_init_io(smdk2410_iodesc,ARRAY_SIZE(smdk2410_iodesc))下面来看一下s3c24xx_init_io函数:void__inits3c24xx_init_io(structmap_desc*mach_desc,intmach_size){/*registerourio-tables*/iotable_init(s3c_iodesc,ARRAY_SIZE(s3c_iodesc));}iotable_init内核提供,定义如下:/**Createthearchitecturespecificmappings*/void__initiotable_init(structmap_desc*io_desc,intnr){inti;for(i=0;inr;i++)create_mapping(io_desc+i);}由上知道,smdk2410_map_io终调用iotable_init建立映射表。iotable_init函数的参数有两个:一个是map_desc类型的构造体,另一个是该构造体的数量nr。这里关键的就是structmap_desc。map_desc构造体定义如下:/*include/asm-arm/mach/map.h*/structmap_desc{unsignedlongvirtual;unsignedlongphysical;unsignedlonglength;unsignedinttype;};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]/*minimalIOmapping*/staticstructmap_descs3c_iodesc[]__initdata={IODESC_ENT(GPIO),IODESC_ENT(IRQ),IODESC_ENT(MEMCTRL),IODESC_ENT(UART)};IODESC_ENT宏如下:#defineIODESC_ENT(x){(unsignedlong)S3C24XX_VA_##x,S3C2410_PA_##x,S3C24XX_SZ_##x,MT_DEVICE}展开后等价于:staticstructmap_descs3c_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定义如下:voids3c2410_gpio_cfgpin(unsignedintpin,unsignedintfunction){void__iomem*base=S3C2410_GPIO_BASE(pin);unsignedlongmask;unsignedlongcon;unsignedlongflags;if(pinS3C2410_GPIO_BANKB){mask=1S3C2410_GPIO_OFFSET(pin);}else{mask=3S3C2410_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定义如下:#defineS3C2410_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里面定义如下:staticstructcpu_tablecpu_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__inits3c2410_map_io(structmap_desc*mach_desc,intmach_siz

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论