4412裸机程序之mmu
来源:互联网 发布:仁王pc版帧数优化补丁 编辑:程序博客网 时间:2024/06/01 09:14
通过内存权限的检查可以保证每个进程使用的内存不被其他进程破坏。具体操作系统怎么运用MMU的就比较复杂了,我们只看看最原始的裸机程序怎么配置寄存器
操作MMU建立虚拟地址到物理地址映射,了解其原理。
ARM提供4种映射长度:段(1M),大页(64K),小页(4K),极小页(1k)
按1M的长度映射就是说一段1M的虚拟地址映射一段1M的物理地址,这1M的地址访问权限是一样的,明显如果按1k,4k映射,内存访问权限将控制的更精细,当然也更复杂。
我们看看1M的精度怎么映射,假设要映射虚拟地址范围(0x0~0x4000000)到物理地址范围(0xB0000000~0xB4000000), 每0x100000的地址长度是1M,那么范围就是64M.
这个映射是以1M对齐的,就是要已(0x0~0x100000)这样映射,而不能(0x1~0x100001),可以看出虚拟地址和物理地址低20位变化是一样的,这样我们只需要一个4byte的内存空间
存放每1M的虚拟地址右移20后与物理地址右移20位建立映射,总共4*64byte。代码大致如下:
unsigned long va = 0x0;
unsigned long pa = 0xB0000000;
while(va<0x4000000){
ttb[va >> 20] = pa | 2;
va += 0x100000;
pa += 0x100000;
}
这样给定一个虚拟地址0x3000400,右移20作为ttb的index就可以找到其后12位对应的物理地址0xB3000000+0x400就是物理地址,当然这样运算是mmu自己做的,我们只需要把ttb的
内存地址附给mmu的寄存器。上面的过程叫建立页表,页表建完后,启动MMU,我们操作的就是虚拟地址了。启动MMU是操作cp15协处理器,下面代码会有说明,了解下。
下面的例子我们用虚拟地址来点led.
#include "regs.h"
void (*uart_asm_putc)(int c) = 0x0202391c;
void (*uart_asm_putx)(int x) = 0x02023940;
#define GPM4CON (*(volatile unsigned int *)0xB10002E0)
#define GPM4DAT (*(volatile unsigned int *)0xB10002E4)
void init_ttb(unsigned long *ttb_base);
void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa);
void memset(char *buf, char ch, int size);
void led_blink(void);
void delay(volatile int time)
{
for(; time > 0; time-- )
;
}
void main(void)
{
unsigned long c1_flags, ttb = 0x73000000;
volatile int *p = 0x52345678;
*p = 0x8;
init_ttb(ttb);
mmap(ttb, 0x12345678, 0x52345678);
mmap(ttb, 0xB10002E0, 0x110002E0);
c1_flags = 1 | (1 << 3) | ( 1 << 11) | (1 << 28);
__asm__ __volatile__ (
"mvn r0, #0 \n"
"mcr p15, 0, r0, c3, c0, 0\n"
"mcr p15, 0, %1, c2, c0, 0\n" //configure ttb
"mrc p15, 0, r0, c1, c0, 0\n"
"orr %0, r0, %0\n"
"mcr p15, 0, %0, c1, c0, 0\n" //enable mmu
:
: "r" (c1_flags), "r" (ttb)
: "r0"
);
p = 0x12345678;
uart_asm_putc('\r');
uart_asm_putc('\n');
uart_asm_putc('c');
uart_asm_putc('y');
uart_asm_putc('j');
uart_asm_putc(':');
uart_asm_putx(*p);
uart_asm_putc('\r');
uart_asm_putc('\n');
led_blink();
}
void init_ttb(unsigned long *ttb_base)
{
unsigned long va, pa;
memset(ttb_base, 0x00, 16 * 1024 );
for (va = 0x00000000; va < 0x10000000; va += 0x100000) { //Others
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
for (va = 0x10000000; va < 0x14000000; va += 0x100000) { //SFR
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
for (va = 0x40000000; va < 0x80000000; va += 0x100000) { //DRAM
pa = va;
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
}
void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa)
{
ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;
}
void memset(char *buf, char ch, int size)
{
int i;
for (i = 0; i < size; i ++)
buf[i] = ch;
}
void led_blink(void)
{
unsigned long tmp = 0;
int i = 0;
/*
* GPM4_0-GPM4_3 设置为输出功能
*/
tmp = GPM4CON;
tmp &= ~0xffff;
tmp |= 0x1111;
GPM4CON = tmp;
/*
* 实现流水灯
*/
while(1)
{
GPM4DAT = i;
if (++i == 16)
i = 0;
delay(9999999);
}
}
代码位置:https://github.com/cyj1988jyc/luoji4412/
- 4412裸机程序之mmu
- MMU 裸机程序
- s3c2440 mmu 裸机程序
- 裸机实验之MMU
- s3c2440的MMU裸机程序
- mini2440裸机之MMU(二)(mmu…
- mini2440裸机之MMU(一)(mmu.…
- 4412裸机程序之ddr
- 4412裸机程序之中断
- 4412裸机程序之IIC
- 4412裸机程序之lcd
- Eclipse开发调试ARM裸机程序(五)MMU调试
- 4412裸机程序之点亮LED
- 4412裸机程序之按键控制LED
- 4412裸机程序之时钟控制
- 4412裸机程序之UART串口
- 02-JZ2440裸机学习之MMU内存管理单元
- tq2440 裸机使用mmu
- spring mvc 报错 expected at least 1 bean which qualifies as autowire candidate for this depend
- 4412裸机程序之ddr
- 解决android签名引起使用第三方平台的不便(如百度地图,QQ,微信等)
- Linux SPI总线和设备驱动架构之一:系统概述
- IAR使用小技巧之群英荟萃
- 4412裸机程序之mmu
- POJ 1321 棋盘问题
- [bat][批处理][自动化测试]用批处理实现以日期和时间做文件文件夹名
- Spark修炼之道(进阶篇)——Spark入门到精通:第二节 Hadoop、Spark生成圈简介
- 徒步一千里 1930年 (長白縣)
- Volley源码分析
- python modules: os, sys, platform
- sicily 1242. Suit Distribution
- android TypedValue.applyDimension()的作用