首先要了解210板子的内存配置情况,我的板子是512M内存,DMC0上接了256M,DMC1接了256M,为了保证地址连续,内存地址只能是0x30000000 ~ 0x4FFFFFFF
第一步运行start.S:
这里判断当前是否已经正常启动,如果r1 = r2,说明uboot已完成自拷贝,则跳转到after_copy,在after_copy中设置MMU映射表之后,开始正常运行初始化板子。
after_copy:
我们直接看copy_from_nand
/*
* copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
* r0: size to be compared
* Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
*/
.globl copy_from_nand
copy_from_nand:
push{lr}/* save return address */
movr9, r0
movr9, #0x100/* Compare about 8KB */
blcopy_uboot_to_ram
tst r0, #0x0
bnecopy_failed
#if defined(CONFIG_EVT1)
ldrr0, =0xd0020000
#else
ldrr0, =0xd0030000
#endif
ldrr1, _TEXT_PHY_BASE/* 0x23e00000 */
1:ldrr3, [r0], #4
ldrr4, [r1], #4
teqr3, r4
bnecompare_failed/* not matched */
subsr9, r9, #4
bne1b
pop{pc}/* all is OK */
copy_failed:
nop/* copy from nand failed */
bcopy_failed
compare_failed:
nop/* compare failed */
bcompare_failed
看看copy_uboot_toram,因为已经设置栈,可以执行C程序了;
回过头来分析after_copy,在这之前的代码应该都是位置无关码,甚至bl copy_fram_nand都是位置无关的因此都可以正确执行。
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 /*MMU表地址高位清零*/
orr r1, r0, r1/*uboot物理加载地址的 与MMU地址低字节相或,得到0x33exxxxx,及mmu_table的地址*/
mcr p15, 0, r1, c2, c0, 0 /*将r1存入CP15*/
这里将MMU映射表所在基址转换成物理地址,存入TTB寄存器中。考虑到之前dnw下载的那段初始程序(以下简写为usb_dnw_init),这里我也有点疑惑,当执行usb_dnw_init后,dnw就能在0x23e00000处下载uboot了,到底usb_dnw_init有没有做MMU的工作呢。
当我写到这里,发现已经有前辈分析过210的uboot了。可以看看:这里
但是网友没有对MMU机制进行分析,我这里说明一下,
可参考《S3C6410之uboot回炉再造(3)》这篇文章。
#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 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF 128M
* 0xC800_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,128MB
@.word 0x00000000
@.endr
.set __base,0xD00
// 1:1 mapping for debugging with non-cacheable
.rept 0x1000 - 0xD00//对应虚拟地址3.125G ~ 4G, 768MB
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
#else// CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B
经过MMU映射后,0xc000 0000~0xcfff ffff映射到了物理内存0x3000 0000 ~ 0x4FFF FFFF中,这样uboot就能通过dnw下载运行了。