2440 开启MMU

    技术2022-05-20  53

    MMU也属于操作系统核心部分,主要功能:

    a) 通过内存管理单元对每个进程进行不同的物理地址映射,实现了各进程间的相同虚拟地址到独立物理地址空间访问,是操作系统支持多进程的基本,相对多线程操作系统更安全;

    b) 当物理内存不够时可以虚拟到外部存储设备,即使当物理内存不够时也能正常运行程序,当然需要足够的外部存储空间,如nand,nor,harddisk等这些外部存储器容量比内存大的多;

    c) ARM的中断向量表需要在0地址,一般情况bank0为nor flash,当程序从内存运行时,需要开启MMU,映射中断向量表到0地址,否则中断时程序可能跑飞;

     

    1.设置MMU的页表,页表本身存储在内存中(此示例为:0x32000000):

    /* * 设置页表 */ void create_page_table(void) { /* * 用于段描述符的一些宏定义 */ #define MMU_FULL_ACCESS     (3 << 10)   /* 访问权限 */ #define MMU_DOMAIN          (0 << 5)    /* 属于哪个域 */ #define MMU_SPECIAL         (1 << 4)    /* 必须是1 */ #define MMU_CACHEABLE       (0 << 3)    /* cacheable */ #define MMU_BUFFERABLE      (0 << 2)    /* bufferable */ #define MMU_SECTION         (2)         /* 表示这是段描述符 */ #define MMU_SECDESC         (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | /                              MMU_SECTION) #define MMU_SECDESC_WB      (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | /                              MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION) #define MMU_SECTION_SIZE    0x00100000     unsigned long virtuladdr, physicaladdr;     volatile unsigned long *mmu_tlb_base = (unsigned long *)0x32000000;        /*      * Steppingstone的起始物理地址为0,第一部分程序的起始运行地址也是0,      * 为了在开启MMU后仍能运行第一部分的程序,      * 将0~1M的虚拟地址映射到同样的物理地址      */ #if 0     virtuladdr = 0;     physicaladdr = 0;     *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | /                                             MMU_SECDESC_WB; #endif     /*      * 0x56000000是GPIO寄存器的起始物理地址,      * GPBCON和GPBDAT这两个寄存器的物理地址0x56000010、0x56000014,      * 为了在第二部分程序中能以地址0xA0000010、0xA0000014来操作GPBCON、GPBDAT,      * 把从0xA0000000开始的1M虚拟地址空间映射到从0x56000000开始的1M物理地址空间      */     virtuladdr = 0x56000000;//0xA0000000;     physicaladdr = 0x56000000;     *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | /                                             MMU_SECDESC;     /*      * SDRAM的物理地址范围是0x30000000~0x33FFFFFF,      * 将虚拟地址0xB0000000~0xB3FFFFFF映射到物理地址0x30000000~0x33FFFFFF上,      * 总共64M,涉及64个段描述符      */     virtuladdr = 0;//0xB0000000;     physicaladdr = 0x30000000;     while (virtuladdr < 0x04000000)      //0xB4000000     {         *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | /                                                 MMU_SECDESC_WB;         virtuladdr += 0x100000;         physicaladdr += 0x100000;     }     virtuladdr = 0x30000000;//0xB0000000;     physicaladdr = 0x30000000; //映射到相同物理地址,保证MMU开启后能正确取下条指令,否则跑飞     while (virtuladdr < 0xFF000000)      //0xB4000000     {         *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | /                                                 MMU_SECDESC_WB;         virtuladdr += 0x100000;         physicaladdr += 0x100000;     } }

     

    2.ARM通过协处理器p15访问MMU:

    MMU_INIT         stmfd sp!,{r0-r4,lr}         mov    r0, #0x32000000 ;页表基址         mcr    p15, 0, r0, c2, c0, 0         mov    r0, #0x00000001 ;开启MMU,注意开启MMU后地址发生变化,为保证CPU能正确取下以条指令,将虚拟地址0x30000000映射到相同的物理地址0x30000000上,否则程序跑飞。         mcr    p15,0,r0,c1,c0,0         ldmfd sp!,{r0-r4,pc}         END

     

    3.init.s:

                    bl         create_page_table                 bl         MMU_INIT ;                bl         LED_ON                 bl         Main


    最新回复(0)