在 ARM Cortex-A8 上启用 MMU 时出现问题。 CPU是S5PV210

Posted

技术标签:

【中文标题】在 ARM Cortex-A8 上启用 MMU 时出现问题。 CPU是S5PV210【英文标题】:Problems enabling MMU on ARM Cortex-A8. CPU is S5PV210 【发布时间】:2014-12-09 12:38:06 【问题描述】:

这些天我只想写一些裸机代码来处理MMU,经过几天的尝试,我仍然无法使其工作。由于我无法使用串行控制台调试它,而且我没有像 D-STREAM 这样昂贵的调试器,我能做的就是在这里粘贴代码并寻求帮助。 我不想当水蛭,但我真的不知道我还能提供什么信息。

我的 CPU 是基于 cortex-A8 架构的 S5PV210 我想做的只是做一个平面内存映射, 这只是意味着“虚拟地址==物理地址”

之后的代码
 "ldr    pc, =0x30000000\n"

只是闪烁的LED程序。如果在“enable_mmu”中评论这一行

"orr    r0, r0, #0x0001\n"          /* .... .... .... ...1 Enable MMU */

我的 flash led 程序可以正常工作,如果我取消注释,flash led 将停止工作。 这是整个程序

#define ttl_base 0x2F000000
#define MMU_DES_FULL_ACESS (3<<10) 
#define MMU_DES_DOMAIN (0<<5) 
#define MMU_DES_EXECUTE_NEVER (0<<4) 
#define MMU_DES_CACHEABLE (1<<3) 
#define MMU_DES_BUFFERABLE (1<<2) 
#define MMU_DES_SECTION (2) 
#define MMU_DES_ATTRIBUTE (MMU_DES_SECTION|MMU_DES_BUFFERABLE|MMU_DES_CACHEABLE|MMU_DES_EXECUTE_NEVER|MMU_DES_DOMAIN|MMU_DES_FULL_ACESS)
void init_mmu()

    //Create Translation Table for a flat map (Vitual Address == Physical Address)
    u32 virtualaddr,phyaddr;
    u32 *mmu_tlb_base=(u32 *)ttl_base;

    virtualaddr = 0x0;
    phyaddr = 0x0;
    while(1)
    
        *(mmu_tlb_base + (virtualaddr>>20)) = (phyaddr & 0xFFF00000) | (MMU_DES_ATTRIBUTE); //map 0x0x30000000-0x30100000 to 0xB0000000-0xB0100000
        virtualaddr+=0x100000;
        phyaddr+=0x100000;
        if (phyaddr==0x00000000)
        
            break;
        
    


void enable_mmu()

    __asm__(
        "mrc    p15, 0, r0, c1, c0, 0\n"
        "bic    r0, r0, #0x3000\n"
        "mcr    p15, 0, r0, c1, c0, 0\n"    /* Disable Insturection cache */

        "mov    r0, #0\n"   
        "mcr    p15, 0, r0, c7, c5, 0\n"   /*Instruction cache invalidate all*/
        "mcr    p15, 0, r0, c7, c5, 6\n"   /*branch predictor invalidate all*/
        "mcr    p15, 0, r0, c8, c7, 0\n"    /* Invalidate data and instruction TLB */

        /*Invalidate entire Data cache*/
        /*Start*/
        "MRC p15, 1, r0, c0, c0, 0\n" /* Read Cache Size ID */
        "LDR r3, =0x1ff\n"
        "AND r0, r3, r0, LSR #13\n" /* r0 = no. of sets - 1 */
        "MOV r1, #0\n" /* r1 = way counter way_loop */
        "way_loop:\n"
        "MOV r3, #0\n" /* r3 = set counter set_loop */
        "set_loop:\n"
        "MOV r2, r1, LSL #30\n" /* */
        "ORR r2, r3, LSL #5\n" /* r2 = set/way cache operation format */
        "MCR p15, 0, r2, c7, c6, 2\n" /* Invalidate line described by r2 */
        "ADD r3, r3, #1\n" /* Increment set counter */
        "CMP r0, r3\n" /* Last set reached yet? */
        "BGT set_loop\n" /* if not, iterate set_loop */
        "ADD r1, r1, #1\n" /* else, next */
        "CMP r1, #4\n" /* Last way reached yet? */
        "BNE way_loop\n" /* if not, iterate way_loop */
        /*End*/

        /*Data and Instruction barrier*/
        "dsb\n"
        "isb\n"


        "mov    r0, #0\n"  
        "mcr    p15, 0, r0, c2, c0, 2\n" /*Clear L2 Translation Table Entry*/

        "mov    r4, #0x2F000000\n"
        "mcr    p15, 0, r4, c2, c0, 0\n" /*Write L1 Translation Table Entry*/

        "mvn    r0, #0\n"                   
        "mcr    p15, 0, r0, c3, c0, 0\n"    /*Write 0xFFFFFFFF to Domain Access Register, which means no permission check*/

        "mrc    p15, 0, r0, c1, c0, 0\n"    /* Read SCTLR */  
                                            /* .RVI ..RS B... .CAM */ 
        "bic    r0, r0, #0x3000\n"          /* ..11 .... .... .... Clear bit V、bit I */
        "bic    r0, r0, #0x0087\n"          /* .... .... 1... .111 Clear bit B/C/A/M */


        "orr    r0, r0, #0x0002\n"          /* .... .... .... ..1. Enable Aligment Check */
        "orr    r0, r0, #0x0004\n"          /* .... .... .... .1.. Enable Data Caches */
        "orr    r0, r0, #0x1000\n"          /* ...1 .... .... .... Enable Instruction Caches */
        "orr    r0, r0, #0x0800\n"          /* .... 1... .... .... Enble brach prediction */
        "orr    r0, r0, #0x0001\n"          /* .... .... .... ...1 Enable MMU */

        "mcr    p15, 0, r0, c1, c0, 0\n"    /* Write back to SCTLR */
        "ldr    sp, =0x3F000000\n"
        "ldr    pc, =0x30000000\n"
        "loop:\n"
        "b loop\n"
    );

【问题讨论】:

你怎么知道编译器没有把ttb放到r0-r3中?带有硬编码寄存器且没有破坏者的大型内联汇编通常是一件非常糟糕的事情。 @Notlikethat 你是对的。但即使我声明“void enable_mmu(void)__attribute__((naked));”。并且不要使用局部变量。问题仍然存在。 naked 只影响函数序言和结语,这恰好与这里无关(当然它应该是,但你不要告诉编译器你正在丢弃一个被调用者保存的寄存器)。我刚刚尝试编译它,果然 gcc 将ttb 放入 r3 中,所以这也确实是垃圾。我建议将代码更新为不会被轻易破坏的代码 - 无论如何,这么多 asm 可能属于单独的 .S 文件。 我希望如果您关闭缓存,您可能会找到一些信息。尝试 I/D 并一起尝试。这有什么影响吗?您的 vbar 在哪里,您是否正在处理数据中止等。您可以从 FAR/FSR 等处获取有关问题所在的信息。 @Notlikethat Yeah.naked 函数在这里并不重要。但我也说我在上面的评论中也没有使用局部变量 ttb 【参考方案1】:

看来您的页表初始化代码是正确的。但您需要提供MMU_DES_ATTRIBUTE。我认为属性有问题。

【讨论】:

对不起,我忘记粘贴了。 你可以看看我的属性是否正确。我已经更新了我原来的帖子

以上是关于在 ARM Cortex-A8 上启用 MMU 时出现问题。 CPU是S5PV210的主要内容,如果未能解决你的问题,请参考以下文章

ARM-V7和ARM-V8架构的硬件

使用硬件计数器测量 ARM Cortex-A8 上的执行时间

开启 MMU 的逻辑和物理地址?

如何测量 ARM Cortex-A8 处理器中的程序执行时间?

ARM中Cortex-A8,Cortex-M0,Cortex-M3 他们的区别在哪?

1.ARM嵌入式体系结构与接口技术(Cortex-A8版)