微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM学习笔记之——MiniOS

ARM学习笔记之——MiniOS

时间:11-20 来源:互联网 点击:

  1. 但是只分配其1MB的实际物理空间
  2. *进程1:物理地址空间0x30100000-0x301fffff,对应MVA(修正虚拟地址,进程PID<25形成)
  3. *MVA地址空间:0x02000000-0x021fffff
  4. *进程2:物理地址空间0x30200000-0x302fffff
  5. *MVA地址空间:0x04000000-0x041fffff
  6. *.........
  7. *进程23:物理地址空间0x31700000-0x317fffff
  8. *MVA地址空间:0x2E000000-0x2E1fffff
  9. *对应进程24由于MVA地址空间是0x30000000是物理内存起始空间,该空间用来放置页表,并且前面已经用该
  10. *地址空间做了映射,因此它不能被映射成,24号进程的物理地址空间,跳过该进程号24,同样道理,
  11. *跳过进程号25
  12. *进程24:物理地址空间0x31800000-0x318fffff
  13. *MVA地址空间:0x30000000-0x31ffffff
  14. *进程25:物理地址空间0x31900000-0x319fffff
  15. *MVA地址空间:0x32000000-0x33ffffff
  16. */
  17. for(entry_index=1;entry_index<24;entry_index++){
  18. *(mmu_tlb_base+((entry_index*0x02000000)>>20))=(entry_index*0x00100000+SDRAM_BASE)|SEC_DESC;
  19. }
  20. /*
  21. *进程26:物理地址空间0x31A00000-0x31Afffff
  22. *MVA地址空间:0x34000000-0x35ffffff
  23. *.........
  24. *进程62:物理地址空间0x33E00000-0x33Efffff
  25. *MVA地址空间:0xC4000000-0xC5ffffff
  26. */
  27. for(entry_index=26;entry_index
  28. *(mmu_tlb_base+((entry_index*0x02000000)>>20))=(entry_index*0x00100000+SDRAM_BASE)|SEC_DESC;
  29. }
  30. /*
  31. *异常向量表
  32. *0xFFFF0000为高地址异常向量表,可以通常设置CP15,C1寄存器V位,当异常产生时,由硬件自动去0xFFFF0000
  33. *地址处执行异常跳转执行,而不是之前的0地址处异常向量表跳转,我们将该虚拟地址映射到0x33F00000这1MB地址
  34. *空间,同样,将全部miniOS代码拷贝到这1MB地址空间来。
  35. */
  36. *(mmu_tlb_base+(0xffff0000>>20))=((VECTORS_PHY_BASE)|SEC_DESC);
  37. }


完成之后,虚拟地址映射如下:

访问0x33FF0000~0x33FFFFFF 与 0xFFF00000~0xFFFFFFFF地址是同一块物理内存空间。

0xA0000000~0xA01FFFFF地址指向0x00000000~0x001FFFFF,NorFlash物理空间。

2.3系统是怎么开启MMU的,为什么开启了MMU内存地址重映射之后程序还能正常运行?

在开启MMU之前,数据访问是直接访问物理地址。但是开启了MMU后,所有的地址访问都需要通过一次虚拟地址转换。同样一个地址并不一定提向的同一个数据内间。

那在mmu_init()函数开启MMU之后出现什么样的反应呢?

  1. voidmmu_init()
  2. {
  3. unsignedlongttb=MMU_TABLE_BASE;
  4. /*reg1待清除位*/
  5. intreg0,reg1=(VECTOR|ICACHE|R_S_BIT|ENDIAN|DCACHE|ALIGN|MMU_ON);
  6. /*CP15,C1设置位:异常向量表设置在高地址,使用ICACHE,系统采用小端模式,
  7. 使用DCACHE,使用地址对齐检查,开启MMU*/
  8. intCP15_C1_set=(VECTOR|ICACHE|DCACHE|ALIGN|MMU_ON);
  9. __asm{
  10. movreg0,#0
  11. /*使ICaches和DCaches无效*/
  12. mcrp15,0,reg0,c7,c7,0
  13. /*使能写入缓冲器*/
  14. mcrp15,0,reg0,c7,c10,4
  15. /*使指令,数据TLB无效无效*/
  16. mcrp15,0,reg0,c8,c7,0
  17. /*页表基址写入C2*/
  18. mcrp15,0,ttb,c2,c0,0
  19. /*将0x2取反变成0xFFFFFFFD,Domain0=0b01为用户模式,其它域为0b11管理模式*/
  20. mvnreg0,#0x2
  21. /*写入域控制信息*/
  22. mcrp15,0,reg0,c3,c0,0
  23. /*取出C1寄存器中值给reg0*/
  24. mrcp15,0,reg0,c1,c0,0
  25. /*先清除不需要的功能,现开启*/
  26. bicreg0,reg0,reg1
  27. /*设置相关位并开启MMU*/
  28. orrreg0,reg0,CP15_C1_set
  29. mcrp15,0,reg0,c1,c0,0
  30. }
  31. //DPRINTK(KERNEL_DEBUG,"MmuinitOK");
  32. }

刚开始,我在看上面代码的时候,我在想。这个一开启MMU之后,这个函数还能正常返回吗?原来MMU在启时前保存的返回地址(物理地址),在MMU开启后这个地址(虚拟地址)对应的还是原来的物理地址吗?除非一种情况: 虚拟地址与物理地址一致。

上述代码为初始化MMU的函数,当在执行完”mcr p15, 0, reg0, c1, c0, 0“ 指令之后,MMU被开启了。所有的地址访问都要经过MMU转换成物理地址才能访问。而mmu_init()此时运行在SDRAM中0x33FF0000地址域上。由2.2节图中所示,0x30000000~0x33FFFFFF地址空间上的虚拟地址与物理地址是对应的。也就是说,虚拟地址==物理地址。

所以,程序能够正常执行。

2.4main( ) 函数是怎么变成task0的?

OSCreateProcess()函数所创建任务的ID号从1开始计数。至于任务0,就是xmain()函数自己。

xmain()自己怎么跑到task0的位置上去坐着的呢?看main.c代码:

  1. intxmain(void)
  2. {
  3. //PC=0x33FF????,SP=0x33FF0000,MMU=关
  4. pgtb_init();//建立页表
  5. mmu_init();//mmu初始化
  6. //PC=0x33FF????,SP=0x33FF0000,MMU=开
  7. //对UART、IRQ、TIMER0、LED、KEY进行初始化
  8. OS_ENTER_CRITICAL();//关闭中

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top