历史上的今天
今天是:2024年12月23日(星期一)
2021年12月23日 | Tiny4412MMU内存管理
2021-12-23 来源:eefocus
MMU是Memory Management Unit的缩写,中文名是内存管理单元,MMU是由ARM芯片中的cp15协处理器管理,它的作用是负责虚拟内存到物理内存的映射
要将虚拟内存映射为物理内存,就要需要构建一张映射表,那么如何来构建这张映射表将至关重要,目前,32位操作系统提供的虚拟存为4G,每个地址占16位4个字节,如果虚拟内存与物理内存要实现一一对应,那么这个张表的一条记录就要占用8个字节,整张表的大小就为32G,这肯定是不可取的;于是我们就采用另一种方法,我们将一个地址的前12为即2的12次方4k做为基地址,后20位作为偏移量,现在我们只需要将虚拟地址的前12位与物理地址的前12一一对应;这样每条记录8字节,整个表就变为32k,明显小了很多,那么我们在访问的时候就需要通过基地址找到所对应的物理地址然后加上偏移量即可(基地址 + 偏移量);
因此,假如我们需要将虚拟地址0x2ab45678映射到物理地址0x6ab45678,我们就可以先通过映射表找到基地址0x2ab所对应的物理地址为0x6ab00000,然后加上偏移量45678,就可以得到实际的物理地址为:0x6ab45678;
| 0x20000000 | 0x60000000 |
| 0x20100000 | 0x60100000 |
| .... | ... |
| 0x2ab00000 | 0x6ab00000 |
因为我们在存映射表的时候就会有一个地址,所以我们可以将映射表的地址利用起来:假设映射表的地址为0x50000000,因此我们可以这样存:
| 0x6ab00000 |
| .......... |
| 0x60100000 |
| 0x60000000 |
——>0x50000000 +(2ab * 4)
.......
——>0x500000000 +(201 * 4)
——>0x500000000 +(200 * 4)
0x50000000//映射表的地址,这样我们映射表存的地址就只有物理地址了,整个表的大小就只有16k了;
下面我们通过代码实现整个过程:
我们在物理地址0x6ab45678存个数据0x12345678,要是通过虚拟地址0x2ab45678也能访问得到;就说明映射成功,否则映射失败
1 /*将虚拟地址0x2ab12345映射到物理地址0x6ab12345*/
2 int (*printf)(char *, ...) = 0xc3e114d8;
3 void enable_mmu();
4 void init_table(unsigned long *addr);
5
6 int main()
7 {
8 //0x2ab00000 -> 0x6ab00000
9 unsigned long *virt = 0x2ab45678;
10 unsigned long *phys = 0x6ab45678;
11 *phys =0x12345678;
12 printf("phys %xn", *phys);
13 enable_mmu();
14 printf("virt %xn", *virt);
15
16 return 0;
17 }
18
19 void enable_mmu()
20 {
21 /*构建表*/
22 unsigned long addr = 0x50000000;
23 init_table(addr);
24 /*打开mmu*/
25 unsigned long mmu = 0;
26 mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
27 __asm__ __volatile__ (
28 "mov r0, #3n"
29 "MCR p15, 0, r0, c3, c0, 0n"//设置为管理员
30 "MCR p15, 0, %0, c2, c0, 0n"//设置表的地址
31 "MCR p15, 0, %1, c1, c0, 0n"//开启mmu
32 :
33 : "r" (addr), "r" (mmu)
34 :
35 );
36
37 }
38
39 void init_table(unsigned long *addr)
40 {
41 unsigned long va = 0;
42 unsigned long phys = 0;
43
44 //0x20000000 -> 0x60000000
45 //0x2ab00000 -> 0x6ab00000
46 for(va = 0x20000000; va < 0x30000000; va += 0x100000) {
47 phys = va + 0x40000000;
48 addr[va >> 20] = phys | 2;
49 }
50 //0x40000000-0x80000000 -> 0x40000000-0x80000000
51 for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
52 phys = va;
53 addr[va >> 20] = phys | 2;
54 }
55
56 //0x10000000-0x14000000 -> 0x10000000-0x140000000
57 for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
58 phys = va;
59 addr[va >> 20] = phys | 2;
60 }
61
62 }
在开发板运行结果如下:

上一篇:Tiny4412之按键驱动
史海拾趣
|
该系统采用的是Qt4做的应用程序,供银行排队叫号系统使用,图片上的前端应用,实际还有Qt4编写的后台设置程序(需通过“秘密通道”打开) 外接输入输出设备有: 1. 银联刷卡器 2. USB小键盘 3. 串口打印机(串口控制模块) 4. 超声波触摸屏(串口 ...… 查看全部问答> |
|
最近,想研究一下rc电路,并阅读了不知道谁写的一本书《RC电路及其应用》,有了一点体会,描述如下. RC电路一大应用时消火花电路。产生火花电路大都是应用于感性负载,如电机、继电器线圈等 如图所示,当开关k断开时候,根据楞次定律线圈两端产 ...… 查看全部问答> |
|
想做蓝牙~~手头有CSR的BC4。。。想和BLUELAB去开发蓝牙 最近刚接触蓝牙。。。手头有一块CSR的BC4。。。想学习用CSR的 BLUELAB 去开发蓝牙。。。 现在用PSTool可以看到蓝牙固件里的信息,也可以修改波特率什么的。。。那并口应该就算是没问题了吧! 在BLUELAB里是不是可以通过并口跟蓝牙芯片连接。。。 ...… 查看全部问答> |
|
因为客户需要,我们准备开发A4/A3的车载GPS方案。 现在寻求硬件高手合作,如能提供A4/A3开发平台及相关资源的,可以额外另付一定的现金报酬。 另外,如果有方案公司愿意合作的,可以加我QQ详谈,46317857。… 查看全部问答> |
|
用定时器0延时1毫秒然后中断产生一个脉冲信号,然而这个脉冲信号是用定时器1延时2微秒然后中断输出采样值产生的,要想让定时器0,1在同一个程序中运行是不是需要设定优先级啊?单单把两个延时中断程序拼起来总是得不到自己想要的结果,求大神们帮忙~ ...… 查看全部问答> |




