韦东山Linux嵌入式课程社区
直播中

张倩

7年用户 198经验值
私信 关注

同样是设置页表,为什么对不同条目的设置代码有区别?

刚开始学习嵌入式,跟着韦老师视频学到mmu页表设置是有个地方不理解,麻烦前辈们帮我解惑。。。先行致谢!下面把含有疑问的代码帖出来:
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       (1 << 3)    /* cacheable */
#define MMU_BUFFERABLE      (1 << 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;
    unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;

    /*
     * Steppingstone的起始物理地址为0,第一部分程序的起始运行地址也是0,
     * 为了在开启MMU后仍能运行第一部分的程序,
     * 将0~1M的虚拟地址映射到同样的物理地址
     */
    virtuladdr = 0;
    physicaladdr = 0;
    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) |
                                            MMU_SECDESC_WB;

    /*
     * 0x56000000是GPIO寄存器的起始物理地址,
     * GPFCON和GPFDAT这两个寄存器的物理地址0x56000050、0x56000054,
     * 为了在第二部分程序中能以地址0xA0000050、0xA0000054来操作GPFCON、GPFDAT,
     * 把从0xA0000000开始的1M虚拟地址空间映射到从0x56000000开始的1M物理地址空间
     */
    virtuladdr = 0xA0000000;
    physicaladdr = 0x56000000;
    *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) |
                                            MMU_SECDESC;

    /*
     * SDRAM的物理地址范围是0x30000000~0x33FFFFFF,
     * 将虚拟地址0xB0000000~0xB3FFFFFF映射到物理地址0x30000000~0x33FFFFFF上,
     * 总共64M,涉及64个段描述符
     */
    virtuladdr = 0xB0000000;
    physicaladdr = 0x30000000;
    while (virtuladdr < 0xB4000000)
    {
        *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) |
                                                MMU_SECDESC_WB;
        virtuladdr += 0x100000;
        physicaladdr += 0x100000;
    }
}



接下来说说我有疑问的地方。
同样是设置页表,为什么对不同条目的设置代码有区别?(不同的地方已经标红了,有关宏标记成了绿色)
虽然不是社么大问题,但是我还是很想搞明白

回帖(6)

龚旻

2019-4-24 10:30:24
顶顶。。。。。。。。。。。。。。。。。。。
举报

蔡艳

2019-4-24 10:42:47
MMU_SECDESC和MMU_SECDESC_WB的区别就在于是否允许Cache和Write Buffer;而0x56000000是GPIO寄存器的起始地址,对于I/O地址空间,不能使用Csche和Write Buffer。所谓I/O地址空间,就是对于期中的地址连续两次的写操作不能够合并在一起,每次读写操作都鼻血直接访问设备,否侧程序的运行结果无法预料。比如寄存器,非内存的外设(扩展串口,网卡等)。摘自《嵌入式Linux应用开发手册》P112页
举报

郝思雨

2019-4-24 10:57:42
我对于 virtuladdr >> 20 这句不是很理解,我的理解是virtuladdr右移20位~书上说——虚拟地址的为【31:20】用于索引一级页表,找到它所对应的描述符,对应于“(virtuladdr >> 20)”完全不明白,求解释
举报

张旭

2019-4-24 11:10:32
因为虚拟地址映射的单位是以M(2的20次方)为单位的,假设你的在、虚拟地址为0xA0000000,页表的起始地址为0x30000000;那么相对应的描述符应该是存放在页表0x30000A00地址,也就是0x30000000+0xA00,而0xA00就是0xA0000000右移20位。。。个人愚见,不知道您明白我的意思不
举报

更多回帖

发帖
×
20
完善资料,
赚取积分