总结
- 本篇主要分析
内存地址映射
- ARM的段式映射中长度为1MB,那我们整个4G范围内需要4G/1MB=4096个映射单元
代码
1. 内存地址映射1
.macro FL_SECTION_ENTRY base,ap,d,c,b
.word (\base << 20) | (\ap << 10) | \
(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
mmu_table:
.set __base,0
// Access for iRAM
.rept 0x100
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
.rept
和.endr
是一对特征体0x100
就是十进行的256,因此循环了256次,则这一段共256MBFL_SECTION_ENTRY
宏的前20位设置基地址- 循环体中,
__base
初始为0,然后加1再进入FL_SECTION_ENTRY
,类推。 .rept 0x100
可以看成.rept 0x100 - 0x0
,则映射的虚拟地址为0到0x10000000
- 物理地址从0开始,直到0x1000000,因此映射的虚拟地址等于真实地址
- 每执行一次左移20位 (10位是K,20位是M),因此从0到0x100,base和地址的对应关系如下
address | base |
---|---|
0 | 0 |
0x00100000 | 1 |
0x00200000 | 2 |
0x00300000 | 3 |
0x00400000 | 4 |
…… | …… |
0x10000000 | 256(0x100) |
2. 内存地址映射2
// Not Allowed
.rept 0x200 - 0x100
.word 0x00000000
.endr
- 循环了
0x200-0x100=0x100
(256)次,则映射了256MB - 映射的256MB的虚拟地址对应物理地址的0地址
3. 内存地址映射3
.set __base,0x200
// should be accessed
.rept 0x600 - 0x200
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
- 映射了1G(0x400)的内存空间
- 物理地址和虚拟地址都是从0x20000000开始至0x60000000
4. 内存地址映射4
.rept 0x800 - 0x600
.word 0x00000000
.endr
- 映射了512MB(0x200)的空间到0地址
5. 内存地址映射5
.set __base,0x800
.rept 0xb00 - 0x800
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
- 映射了768MB(0x300)的内存空间
- 物理地址和虚拟地址都是从0x80000000至0xb0000000
6. 内存地址映射6
.set __base,0xB00
.rept 0xc00 - 0xb00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
- 映射了256MB(0x100)内存空间
- 物理地址和虚拟地址都是从0xb0000000开始至0xc0000000
7.内存地址映射7
// 0xC000_0000映射到0x2000_0000
.set __base,0x300
//.set __base,0x200
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
- 映射了256MB(0x100)内存空间
- 物理地址从0x30000000到0x40000000
- 虚拟地址从0xc0000000到0xd0000000
8.内存地址映射8
set __base,0xD00
.rept 0x1000 - 0xD00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
- 映射了768MB(0x300)内存空间
- 物理地址和虚拟地址都是从0xd0000000到0x1000000000
总结
虚拟地址(16进制) | 物理地址(16进制) | 长度 |
---|---|---|
0-10000000 | 0-10000000 | 256MB |
10000000-20000000 | 0 | 256MB |
20000000-60000000 | 20000000-60000000 | 1GB |
60000000-80000000 | 0 | 512MB |
80000000-b0000000 | 80000000-b0000000 | 768MB |
b0000000-c0000000 | b0000000-c0000000 | 256MB |
c0000000-d0000000 | 30000000-40000000 | 256MB |
d0000000-100000000 | d0000000-0x100000000 | 768MB |
- 因此此MMU的功能只是把虚拟地址的0xc0000000-0xd0000000映射到0x30000000-0x40000000
- 除了两段不能访问的虚拟地址之外都和物理地址相同
- 物理地址中的30000000-40000000做了
两次映射
,因此在此uboot中,虚拟地址30000000-40000000与c0000000-d0000000是同一段地址
,只不过可能处在不同的板载芯片中。