s5pv210 USB启动模式下的内存映射

2510阅读 0评论2016-01-24 edaplayer
分类:嵌入式

之前写的原帖地址

本帖讨论在usb启动模式中,uboot为何能在能在0x23e00000地址处运行。


先从nand启动模式说起。
x210因为只有512MB内存,nand启动模式下,初始化后内存物理地址空间为0x3000 0000 ~ 0x4FFF FFFF。
在x210_nand.h中有代码基址的定义:


#define MEMORY_BASE_ADDRESS        0x30000000


/* base address for uboot */
#ifdef CONFIG_ENABLE_MMU
#define CFG_UBOOT_BASE                0xc3e00000
#else
#define CFG_UBOOT_BASE                0x33e00000  /*yan*/
//#define CFG_UBOOT_BASE                0x23e00000  /*yan*/
#endif


#define CFG_PHY_UBOOT_BASE        MEMORY_BASE_ADDRESS + 0x3e00000
#define CFG_PHY_KERNEL_BASE        MEMORY_BASE_ADDRESS + 0x8000


一、nand启动
上电启动后,加载运行BL1,初始化硬件后,执行uboot中的 copy_uboot_to_ram 函数:
int copy_uboot_to_ram (void)
{
        int large_block = 0;
        int i;
        vu_char id;


        int rv;


        NAND_CONTROL_ENABLE();
        NAND_ENABLE_CE();
        NFCMD_REG = NAND_CMD_READID;
        NFADDR_REG =  0x00;


        /* wait for a while */
        for (i=0; i<200; i++);
        id = NFDATA8_REG;
        id = NFDATA8_REG;


        if (id > 0x80)
                large_block = 1;
        else
                return -1;        // Do not support small page (512B) any more


        /* read NAND blocks */
        rv = nandll_read_blocks(CFG_PHY_UBOOT_BASE, COPY_BL2_SIZE);


#if defined(CONFIG_SECURE_BOOT)
        rv = Check_Signature((SecureBoot_CTX *)SECURE_BOOT_CONTEXT_ADDR,
                        (unsigned char *)CFG_PHY_UBOOT_BASE,
                        (1024*512 - 128),
                        (unsigned char *)(CFG_PHY_UBOOT_BASE + (1024*512-128)),
                        128);
        if (rv != SB_OK)
                while(1);
#endif


        return rv;
}
这里拷贝从nand flash 拷贝 uboot.bin到0x33e0 0000,大小为COPY_BL2_SIZE = 0x80000。


那么问题来了,nand启动时uboot 在0x33e0 0000处运行,然而,首次下载uboot时,使用dnw下载uboot.bin到0x23e0 0000,此时uboot位于0x23e0 0000,运行地址如何对应得上?不同的物理地址能运行同一个uboot?
我猜测是因为启用了MMU的关系.
在start.S中,配置MMU的代码如下
after_copy:


#if defined(CONFIG_ENABLE_MMU)
enable_mmu:
        /* enable domain access */
        ldr        r5, =0x0000ffff
        mcr        p15, 0, r5, c3, c0, 0                @load domain access register


        /* Set the TTB register */
        ldr        r0, _mmu_table_base
        ldr        r1, =CFG_PHY_UBOOT_BASE
        ldr        r2, =0xfff00000
        bic        r0, r0, r2
        orr        r1, r0, r1
        mcr        p15, 0, r1, c2, c0, 0


        /* Enable the MMU */


首先利用_mmu_table_base和0xfff00000进行位清除,得到当前uboot运行状态下,_mmu_table_base的低地址,存到r0。   r1存放CFG_PHY_UBOOT_BASE
CFG_PHY_UBOOT_BASE即0x33e00000和_mmu_table_base低地址进行或运算,得到0x33e_____,存入协处理器的转换表基址。
但依然分析不出代码如何能在0x23e00000运行。


第二篇:
我的板子是512M的s5pv210,在usb启动模式下,可以通过dnw直接下载到三星的官方uboot中运行,
具体步骤参考Sate210 android使用手册V1.0,百度文库就有。
我查看了源码,对链接地址有些疑惑。三星的uboot在aftercopy之后开启了MMU功能,
我的板子是512M内存,物理内存地址空间为0x3000 0000 ~0x4FFF FFFF,uboot源码设置的链接地址为0xc3e00000


根据uboot的mmu映射表:
#ifdef CONFIG_ENABLE_MMU


    #ifdef CONFIG_MCP_SINGLE
/*
* MMU Table for SMDKC110
* 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed
* 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF VA = PA
* 0xC000_0000 -- 0xCFFF_FFFF => A:0x3000_0000 -- 0x3FFF_FFFF 256M
* 0xD000_0000 -- 0xDFFF_FFFF => Not Allowed
* 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF VA = PA
*/


    /* form a first-level section entry */
.macro FL_SECTION_ENTRY base,ap,d,c,b
    .word (\base << 20) | (\ap << 10) | \
          (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
.section .mmudata, "a"
    .align 14
    // the following alignment creates the mmu table at address 0x4000.
    .globl mmu_table
mmu_table:
    .set __base,0
    // Access for iRAM
    .rept 0x100            //对应虚拟地址0 ~ 256M
    FL_SECTION_ENTRY __base,3,0,0,0
    .set __base,__base+1
    .endr


    // Not Allowed
    .rept 0x200 - 0x100    //对应虚拟地址256M ~ 512M
    .word 0x00000000
    .endr


    .set __base,0x200
    // should be accessed
    .rept 0x600 - 0x200//对应虚拟地址512M ~ 1.5G
    FL_SECTION_ENTRY __base,3,0,1,1
    .set __base,__base+1
    .endr


    .rept 0x800 - 0x600//对应虚拟地址1.5G ~ 2G
    .word 0x00000000
    .endr


    .set __base,0x800
    // should be accessed
    .rept 0xb00 - 0x800//对应虚拟地址2 ~ 2.75G
    FL_SECTION_ENTRY __base,3,0,0,0
    .set __base,__base+1
    .endr


/*    .rept 0xc00 - 0xb00
    .word 0x00000000
    .endr */


    .set __base,0xB00
    .rept 0xc00 - 0xb00//对应虚拟地址2.75G ~ 3G 256MB
    FL_SECTION_ENTRY __base,3,0,0,0
    .set __base,__base+1
    .endr


    .set __base,0x300
    // 256MB for SDRAM with cacheable
    .rept 0xD00 - 0xC00//对应虚拟地址3G ~ 3.25G, 256MB
    FL_SECTION_ENTRY __base,3,0,1,1
    .set __base,__base+1
    .endr


    // access is not allowed.
    @.rept 0xD00 - 0xC80//对应虚拟地址3G ~ 3.125G
    @.word 0x00000000
    @.endr


    .set __base,0xD00
    // 1:1 mapping for debugging with non-cacheable
    .rept 0x1000 - 0xD00//对应虚拟地址3.125G ~ 4G,
    FL_SECTION_ENTRY __base,3,0,0,0
    .set __base,__base+1
    .endr    
    
    #else    // CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B


内存映射后的地址为:0xC0000000~0xCFFF FFFF请教各位前辈,dnw下载uboot到DDR中,
链接地址(MMU转换后为0x33e00000)与0x23e0 0000并不对应,后面的代码为什么还能正常运行呢?

我猜测是DDR初始化配置造成的,当CPU访问0x2000 0000的时候,其实和访问0x3000 0000是访问同一个DDR真实地址,
因为MENCONFIG0寄存器可以屏蔽地址高位,恩,应该是因为这个。这不是MMU映射造成的,
是cpuDDR初始化配置时屏蔽了地址高位。呵呵,三星的cpu真是方便阉割啊,1G内存变成512M还能用dnw下载uboot。
唉,求人不如求己啊,虽然想通了这是很简单的问题,但是毕竟板子和程序都不是自己设计的,谁能想起还有这个细节。蛋疼。
我烧写三星uboot后重启执行md 20000000,此时死机了,
比对uboot源码,说明uboot的DDR配置和x210_usb.bin(原名V210_USB.BL2.bin)的DDR配置是不同的,
如果相同后面跑内核就有问题了。
猜测x210_usb.bin(原名V210_USB.BL2.bin)的DDR应该配MENCONFIG0 = 0x30E01313,
这样无论访问0x23e0 0000还是访问0x33e0 0000,都会打开Xm1_CS0片选。


上一篇:arago rootfs的sysvinit启动流程
下一篇:AM335x SGX+OPENGL移植笔记