Embeded linux之地址映射

一、板级文件

通常会由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++);
  }
}

时间: 2024-08-09 09:49:34

Embeded linux之地址映射的相关文章

Embeded linux 之 cifs文件系统

待整理 转自: http://blog.csdn.net/yuanbinquan/article/details/51734705 简介 CIFS (Common Internet File System) 通用Internet文件系统 在windows主机之间进行网络文件共享是通过使用微软公司自己的CIFS服务实现的. 功能 CIFS 可以使您达到以下功能: 1.访问服务器本地文件并读写这些文件 2.与其它用户一起共享一些文件块 3.在断线时自动恢复与网络的连接 4.使用统一码(Unicode

Embeded linux之probe

一.基于linux-3.18.20.mac驱动 二.启动时机: 所谓的"probe",是指在Linux内核中,如果存在相同名称的device和device_driver,内核就会执行device_driver中的probe回调函数,而该函数就是所有driver的入口,可以执行诸如硬件设备初始化.字符设备注册.设备文件操作ops注册等动作("remove"是它的反操作,发生在device或者device_driver任何一方从内核注销时. 将struct device

Embeded linux之内核编译错误警告汇总

错误A: WARNING: drivers/spi/hi_spi.o(.data+0x0): Section mismatch in reference from the variable hi_spi_platform_driver to the function .init.text:hi_spi_probe()The variable hi_spi_platform_driver referencesthe function __init hi_spi_probe()If the refe

Embeded linux之Uboot参数与内核

一.内核查参方式: 1.1 mtd方式 文件形式,待补 1.2 ioremap 驱动+应用,待补 1.3 mtd_debug 软件移植,待补 1.4 fw_printenv 1.4.1 工具生成方法: uboot_source_tree # make ARCH=arm CROSS_COMPILE=arm-linux-gcc env uboot_source_tree/tools/env下得到fw_printenv与fw_env.config 1.4.2 将工具与配置文件放到板子文件系统上 1.4

Embeded linux之调试内核

KGDB: 注意:Linux内核从 2.6.26开始已经在内部集成kgdb,只需要配置kgdb并重新编译2.6.26(或更高)内核即可 本文使用内核3.0.35.CPU为imx6 1.配置内核支持kdb make menuconfig Kernel hacking  ---> [*] KGDB: kernel debugger  ---> <*> KGDB: use kgdb over the serial console  [*] KGDB: internal test suit

Embeded linux之RTL8188EU/RTL8188ETV使用

一.kernel:3.18.20 [*] Networking support  ---> -*-   Wireless  ---> <*> cfg80211 - wireless configuration API [*] nl80211 testmode command [*] enable developer warnings [*] cfg80211 regulatory debugging [*] enable powersave by default  [*] cfg8

Embeded linux之移植dropbear

红字加粗为编译器不同.路径不同需要注意修改的地方 一.源码包下载: zlib官方下载:http://www.zlib.net/ dropbear官方下载:https://matt.ucc.asn.au/dropbear/dropbear.html 本文使用版本: zlib-1.2.8 dropbear-2016.74 下面链接有已上传的配置好的源码包 二.创建工作目录 安装路径: /opt/dropbear_ssh/install/ 源码路径: /opt/dropbear_ssh/source/

Embeded linux之移植iptables

一.内核环境: linux-3.4.35 -*- Networking support  ---> Networking options  ---> [*] Network packet filtering framework (Netfilter)  ---> IP: Netfilter Configuration  ---> <*> IP tables support (required for filtering/masq/NAT) //iptables <

Embeded Linux 之 PHY

PHY一般具备两种接口: 1.数据接口:千兆RGMII.百兆或十兆RMII\MII 用来传输网络数据. TXC由MAC产生,RXC由PHY产生. TXC与RXC在千兆网络为125MHz,TXC与RXC在百兆网络为25MHz,TXC与RXC在十兆网络为2.5MHz.  TXD[3:0] 和RXD[3:0] 数据传输时在时钟的边沿进行采样. 2.管理接口:数据MDIO和时钟MDC 用来访问数据. 举例读写时序图: 未完待续....