一、板级文件

通常会由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,
  .timer       = &Chipname_sys_timer,
  .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;    //类型
};

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

static 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
  }
};

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

以后直接*(volatile 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
以后直接*(volatile 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/compiler-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--)

  {

    create_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++);
  }
}

转载于:https://www.cnblogs.com/pokerface/p/6777581.html

Embeded linux之地址映射相关推荐

  1. 深度剖析Linux内核地址映射机制

    深度剖析Linux内核地址映射机制 1.虚拟空间数据结构   2.进程虚拟空间  3.内存映射 视频讲解如下,点击观看: Linux内核开发系列第7讲--深度剖析Linux内核地址映射机制 C/C++ ...

  2. linux内核地址映射,Linux内核设备驱动地址映射笔记整理

    #include #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)//cookie表示物理地址, size表示映射 ...

  3. linux安装各种文件格式,Embeded linux中的各类文件系统

    Cramfs:(优点:只读,目的:不可更改文件.防入侵) 1.下载cramfs-1.1源码工具 http://files.cnblogs.com/files/pokerface/cramfs-1.1. ...

  4. Embeded linux OS Reading Notes

    Linux: 1 单内核模式 Linux是单内核模式,和外部程序在不同的内存地址空间,程序只有通过:System Call界面访问. Linux的单内核模式是动态的,通过Module. 2 没有用户线 ...

  5. linux设备probe,你了解Embeded linux中的probe

    一.基于linux-3.18.20.mac驱动 二.启动时机: 所谓的"probe",是指在Linux内核中,如果存在相同名称的device和device_driver,内核就会执 ...

  6. linux arm 地址映射 ioremap_nocache 使用,ioremap_nocache 函数分析

    oremap_nocache()函数我想大家都不陌生,现在我就把此函数分析一下,不当之处请大家谅解! 对于EHCI来说它把它本身的寄存器和内存映射到内存中区!但是站在CPU的角度来说,我们无法直接访问 ...

  7. Embeded linux之移植iptables

    一.内核环境: linux-3.4.35 -*- Networking support  ---> Networking options  ---> [*] Network packet ...

  8. linux编译mmc驱动,Embeded linux之MMC驱动

    一.注册平台设备 platform_device_register(&usr_mci_device); 二.填写平台设备结构体 static struct platform_device us ...

  9. Embeded linux之移植boa

    一.解压 a) tar xvf boa-0.94.13.tar.gz 二.设置交叉编译工具 a) vi /boa-0.94.13/src/Makefile b)  三.修改源码 a) vi /boa- ...

最新文章

  1. js关闭窗口无提示,不支持FF
  2. Java Review - 并发编程_ConcurrentLinkedQueue原理源码剖析
  3. mqtt协议详解_IoT物联网设备上云技术方案详解
  4. char 和 varchar 的区别,数据库索引B+树
  5. python数字类型floatcomplexint_浅谈python 四种数值类型(int,long,float,complex)
  6. python3urllib常见使用_Python3 urllib常用操作
  7. 与国际接轨,中国人慎用这些汉字取名(最后一段对话,笑到喷饭!!)
  8. 吴恩达机器学习作业Python实现(五):偏差和方差
  9. Vue-网页版音乐播放器实现(网易云音乐源)
  10. JS JQUERY获取两个时间相差几个月
  11. #655 – 冒泡事件可能会被某些控件屏蔽(Bubbling Mouse Events Swallowed by Some Controls)
  12. Git和Repository简明理解(GitHub是什么?)
  13. 天载免息股票热点轮动太快
  14. 如何提取abaqus的位移和其坐标
  15. Light OJ 1214
  16. 模电笔记二(第一章第二小节)
  17. 基于HI3516DV300平台GT911触摸屏调试
  18. 本分初心,vivo以科技之力守护“唯一的地球”
  19. 将多个月的nc数据文件合并成一个(月平均)
  20. MySQL数据库,从入门到精通:第十四篇——MySQL视图详解

热门文章

  1. OpenGL基础35:帧缓冲(下)之简单图像处理
  2. bzoj 3381: [Usaco2004 Open]Cave Cows 2 洞穴里的牛之二(RMQ)
  3. bzoj 1264: [AHOI2006]基因匹配Match(树状数组)
  4. bzoj 1682: [Usaco2005 Mar]Out of Hay 干草危机(最小生成树)
  5. bzoj 4491: 我也不知道题目名字是什么(线段树区间和并)
  6. [Python] zip() 函数
  7. RoaringBitmap 原理
  8. jquery中ajax应用——load()函数
  9. MySQL 8.0查找my.ini文件位于C:\ProgramData\MySQL\MySQL Server 8.0
  10. 在linux中,boot与uboot有什么区别?