一步一步写嵌入式操作系统----MMU

MMU作为一个硬件单元有把虚拟地址转换成物理地址的作用,操作系统可以让用户运行大量的程序,这些程序都需要分配内存,而一段程序重复运行的时候,如果没有MMU,一段物理地址不可能被重复使用,而有MMU的时候可以把同一虚拟地址映射到不同的物理地址段,这样就避免地址冲突了。而且大家都有体验,以linux为例,存在交换分区,它可以把硬盘的存储空间映射到虚拟地址中,这样一来相当于内存被扩容了,当然这样的便利也伴随着访问效率的降低。

mmu.c

/*mask for page table base addr*/
#define PAGE_TABLE_L1_BASE_ADDR_MASK	(0xffffc000)

#define VIRT_TO_PTE_L1_INDEX(addr)		(((addr)&0xfff00000)>>18)

#define PTE_L1_SECTION_NO_CACHE_AND_WB	(0x0<<2)
#define PTE_L1_SECTION_DOMAIN_DEFAULT	(0x0<<5)
#define PTE_ALL_AP_L1_SECTION_DEFAULT	(0x1<<10)

#define PTE_L1_SECTION_PADDR_BASE_MASK	(0xfff00000)
#define PTE_BITS_L1_SECTION				(0x2)

#define L1_PTR_BASE_ADDR				0x30700000
#define PHYSICAL_MEM_ADDR				0x30000000
#define VIRTUAL_MEM_ADDR				0x30000000
#define MEM_MAP_SIZE					0x800000
#define PHYSICAL_IO_ADDR				0x48000000
#define VIRTUAL_IO_ADDR					0xc8000000
#define IO_MAP_SIZE						0x18000000

void start_mmu(void)
{
	unsigned int ttb = L1_PTR_BASE_ADDR;

	asm (
		"mcr p15,0,%0,c2,c0,0\n"    /* set base address of page table*/
		"mvn r0,#0\n"                  
		"mcr p15,0,r0,c3,c0,0\n"    /* enable all region access*/

		"mov r0,#0x1\n"
		"mcr p15,0,r0,c1,c0,0\n"    /* set back to control register */
		"mov r0,r0\n"
		"mov r0,r0\n"
		"mov r0,r0\n"
		:
		: "r" (ttb)
		:"r0"
	);
}

unsigned int gen_l1_pte(unsigned int paddr)
{
	return (paddr & PTE_L1_SECTION_PADDR_BASE_MASK) | PTE_BITS_L1_SECTION;
}

unsigned int gen_l1_pte_addr(unsigned int baddr, unsigned int vaddr)
{
	return (baddr & PAGE_TABLE_L1_BASE_ADDR_MASK) | VIRT_TO_PTE_L1_INDEX(vaddr);
}

void init_sys_mmu(void)
{
	unsigned int pte;
	unsigned int pte_addr;
	int j;

	for(j = 0; j < MEM_MAP_SIZE>>20; j++) {
		pte = gen_l1_pte(PHYSICAL_MEM_ADDR + (j<<20));
		pte |= PTE_ALL_AP_L1_SECTION_DEFAULT;
		pte |= PTE_L1_SECTION_NO_CACHE_AND_WB;
		pte |= PTE_L1_SECTION_DOMAIN_DEFAULT;
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, VIRTUAL_MEM_ADDR + (j<<20));
		*(volatile unsigned int *)pte_addr = pte;
	}

	for(j = 0; j< IO_MAP_SIZE>>20; j++) {
		pte = gen_l1_pte(PHYSICAL_IO_ADDR+(j<<20));
		pte |= PTE_ALL_AP_L1_SECTION_DEFAULT;
		pte |= PTE_L1_SECTION_NO_CACHE_AND_WB;
		pte |= PTE_L1_SECTION_DOMAIN_DEFAULT;
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, VIRTUAL_IO_ADDR + (j<<20));
		*(volatile unsigned int *)pte_addr = pte;
	}
}

 

一步步嵌入式操作系统 linux平台实现代码 step 0 准备开发环境 1 安装交叉编译工具 sudo apt-get install gcc-arm-none-eabi sudo apt-get install gcc-arm-linux-gnueabihf sudo apt-get install g++-arm-linux-gnueabihf 2 手边编译skyeye 用apt命令安装的skyeye模拟器版本(1.2.5)有bug,需要手动编译更高版本的skyeye 下载并解压skyeye 1.2.6_rc1的代码, ~/Downloads/skyeye-1.2.6_rc1 根据执行skyeye-1.2.6_rc1/INSTALL的说明 1 执行 ./configure 2 执行 make 后 编译错误1: In file included from /usr/include/fcntl.h:289:0, from nandflash/nandflash_smallblock.c:19: In function ‘open’, inlined from ‘nandflash_sb_setup’ at nandflash/nandflash_smallblock.c:519:24: /usr/include/x86_64-linux-gnu/bits/fcntl2.h:50:4: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments __open_missing_mode (); 解决方法: 修改skyeye-1.2.6_rc1/device/nandflash/nandflash_smallblock.c 519行 if ((nf->fdump= open(dev->dump, FILE_FLAG)) < 0) 改为: if ((nf->fdump= open(dev->dump, FILE_FLAG, 0777)) < 0) 编译错误2: gcc -g -O2 -o skyeye skyeye.o ./utils/libutils.a ./arch/arm/libarm.a ./device/libdev.a ./arch/mips/libmips.a ./arch/ppc/libppc.a ./arch/bfin/libbfin.a ./arch/mips/libmips.a ./arch/coldfire/libcoldfire.a -lc ./utils/libutils.a -lbfd -lm -lc ./arch/mips/libmips.a(decoder.o):在函数‘decode’中: /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1079:对‘sign_extend_UInt32’未定义的引用 /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1105:对‘sign_extend_UInt32’未定义的引用 /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1049:对‘sign_extend_UInt32’未定义的引用 /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1027:对‘sign_extend_UInt32’未定义的引用 /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1013:对‘sign_extend_UInt32’未定义的引用 ./arch/mips/libmips.a(decoder.o):/home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:1001: 跟着更多未定义的参考到 sign_extend_UInt32 ./arch/mips/libmips.a(decoder.o):在函数‘decode’中: /home/kolya/Downloads/skyeye-1.2.6_rc1/arch/mips/common/decoder.c:240:对‘divide_UI
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值