嵌入式Linux移植之内存初始化和地址映射

本文详细介绍了嵌入式Linux内核在移植过程中内存初始化和地址映射的关键概念,如PHYS_OFFSET和PAGE_OFFSET。讲解了如何根据开发板配置确定内存布局,并通过paging_init进行页表初始化。还提到了mem参数的优先级高于atag_mem,并分析了在小内存设备中mem=参数的重要性,以及预留内存的原因。最后,讨论了iotable_init和ioremap函数在内存映射中的作用,并以I2C驱动为例进行了说明。
摘要由CSDN通过智能技术生成

Linux内核有两个重要的宏:PHYS_OFFSET和PAGE_OFFSET。PHYS_OFFSET是物理内存的起始地址,PAGE_OFFSET是Linux内核空间的虚拟起始地址(默认为0xC0000000,可通过menuconfig配置,CONFIG_PAGE_OFFSET)。PHYS_OFFSET可通过menuconfig配置(CONFIG_PHYS_OFFSET),但一般不直接配置。 如果定义了CONFIG_ARM_PATCH_PHYS_VIRT,则内核会根据实际所在的地址调整PHYS_OFFSET的值。

内核镜像生成的时候需要PHYS_OFFSET和PAGE_OFFSET对应的物理地址,在Makefile.boot中指定。对于SMDK2440开发板,则为arch/arm/mach-s3c24xx/Makefile.boot,如下,zreladdr-y即为__pa(PAGE_OFFSET+TEXT_OFFSET)(TEXT_OFSSET在makefile中写死了为0x8000)。params_phys-y即为PHYS_OFFSET

ifeq ($(CONFIG_PM_H1940),y)
	zreladdr-y	+= 0x30108000
	params_phys-y	:= 0x30100100
else
	zreladdr-y	+= 0x30008000
	params_phys-y	:= 0x30000100
endif
Linux内核中内存初始化主要是初始化内存的地址范围和布局,以及建立页表(MMU),不会再初始化内存控制器。内存控制器在u-boot中已经初始化好并且已经把代码拷贝到内存运行,初始化内存控制器也可能导致内存中的数据异常。uboot中可以通过两种方式传递内存信息:在启动参数中使用mem=xxx或者使用atag_mem。

        对于mem=xxx参数,在early_param中初始化memblock,这里实际上添加了一个起始地址为PHYS_OFFSET,大小为mem=指定的内存bank。

static int __init early_mem(char *p)
{
	static int usermem __initdata = 0;
	u64 size;
	u64 start;
	char *endp;

	/*
	 * If the user specifies memory size, we
	 * blow away any automatically generated
	 * size.
	 */
	if (usermem == 0) {
		usermem = 1;
		memblock_remove(memblock_start_of_DRAM(),
			memblock_end_of_DRAM() - memblock_start_of_DRAM());
	}

	start = PHYS_OFFSET;
	size  = memparse(p, &endp);
	if (*endp == '@')
		start = memparse(endp + 1, NULL);

	arm_add_memory(start, size);

	return 0;
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值