OK6410,MMU,内存管理 杂谈(2)

  其次,开启MMU后,使用的就是虚拟地址了,所以还要建立程序段的页表,不然一旦开启MMU,CPU去取指令,这个时候发出的就是虚拟地址,但是又没有建立虚拟地址到物理地址的映射表。这样的话,就取不到指令了,程序就崩溃了。所以还需要对代码区建立映射页表。代码区的映射就是将虚拟地址直接转换为物理地址使用。

  将这个地址给映射到0x7F000000区域去。

  unsigned long *ttb = (unsigned long *)0x50000000;//获取基地址

  unsigned long vaddr, paddr;

  vaddr = 0xA0000000;

  paddr = 0x7f000000;

  *(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC;

  //获得一级描述符的地址    并且赋值

  首先申明一个ttb指针,这个指针就指向一级表的基地址,也就是ddr的首地址,0x50000000。然后再申明两个变量,一个表示虚拟地址,一个表示物理地址。

  根据前面的一级段描述符格式,往对应的内存单元写入数据即可。段描述符的高12位是物理地址的高12位,所以首先有一个物理地址和0xFFF00000与的操作,将物理地址的高12位写入到段描述符。

  这里使用*(ttb + (vaddr >> 20))来对对应的页描述符进行赋值。在一级页表中,是通过虚拟地址的高12位来决定偏移是多少。高12位也就是位移20位,所以这里就是加上虚拟地址右移20位的值,也就是取出高12位的值。注意,这里是指针操作,假设这个时候虚拟地址的高12位值是5,那么写的地址不是0x50000005,而是0x50000014。因为指针的数据类型是long型,4个字节,所以加1,地址就会加4,加5,地址就会加5*4=20。

  后面位的配置:

OK6410,MMU,内存管理 杂谈

  设置为访问权限是11,也就是不进行访问权限的检查。将域设置为0。CACHE和write BUFFER都给关掉。因为这只是对一个寄存器的操作,没有必要使用CACHE和write BUFFER。

  这样,就建立好了GPIO的页表。访问虚拟地址0xc7000000,也就是访问物理地址0x7f000000。整个段空间是1Mb。

1.6.2建立代码区的页表

  这个时候,代码已经是在内存中运行的了。所以,直接将内存的所有地址空间进行映射,空间是64MB大小。

  

OK6410,MMU,内存管理 杂谈

  使用的宏

  

OK6410,MMU,内存管理 杂谈

  其实就是多一个开启CACHE和WRITE BUFFER。

  内存映射是映射一片区域,从0x50000000地址开始到0x54000000这64M的虚拟地址给映射到0x50000000地址开始到0x54000000这64M物理地址上去。这样,即使使用虚拟地址去取ddr中数据,也是能够取到的。

  因为一个段是映射的1MB空间,所以总共需要64个段,十六进制也就是0x40。所以在while里面判断是虚拟地址要小于0x54000000。再者,每一个段表示1MB空间,所以虚拟地址和物理地��都要加1MB。也就是0x100000。

  这样,就将页表给建立好了。如果还需要使用其他地址区域,就都得为这些区域建立映射表。

1.6.3开启mmu

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/109bca50bc84383c6504a9d7ada4791f.html