从内部的fireware启动xload开始,xload首先加载的是x-load.lds:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/omap3/start.o (.text) *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .; }
从这段代码的text代码段中可以看出,入口函数的ENTRY 为start函数,位于cpu/omap3/start.s中,这部份代码完成了汇编和C语言的交互,部分代码如下所示:
.globl _start _start: b reset //首先跳入reset函数,不再返回 ldr pc, _hang 。。。。。。 _hang: .word do_hang .word 0x12345678 .word 0x12345678 .word 0x12345678 .word 0x12345678 .word 0x12345678 .word 0x12345678 .word 0x12345678 /* now 16*4=64 */ .global _end_vect _end_vect: .balignl 16,0xdeadbeef /* ************************************************************************* * * Startup Code (reset vector) * * do important init only if we don't start from memory! * setup Memory and board specific bits prior to relocation. * relocate armboot to ram * setup stack * ************************************************************************* */ _TEXT_BASE: .word TEXT_BASE .globl _armboot_start _armboot_start: .word _start /* * These are defined in the board-specific linker script. */ .globl _bss_start _bss_start: .word __bss_start .globl _bss_end _bss_end: .word _end /* * the actual reset code */ reset: /* * set the cpu to SVC32 mode */ ....... next: ...... bl cpy_clk_code /* put dpll adjust code behind vectors */ //完成clk的初始化 /* the mask ROM code should have PLL and others stable */ bl cpu_init_crit //这部分是解决我的问题的关键,这里会调用C语言的内容。 relocate: /* relocate U-Boot to RAM */ 。。。。。。。。。。。。 copy_loop: 。。。。。。。。。 /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub sp, r0, #128 /* leave 32 words for abort-stack */ and sp, sp, #~7 /* 8 byte alinged for (ldr/str)d */ /* Clear BSS (if any). Is below tx (watch load addr - need space) */ clear_bss: ldr r0, _bss_start /* find start of bss segment */ ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear value */ clbss_l: str r2, [r0] /* clear BSS location */ cmp r0, r1 /* are we at the end yet */ add r0, r0, #4 /* increment clear index pointer */ bne clbss_l /* keep clearing till at end */ ldr pc, _start_armboot /* jump to C code */ //从这边开始,其实是进入C语言加载uboot.bin啦, 当然这里会完成串口的初始化,因此系统的信息只有此时才可以printf, _start_armboot: .word start_armboot /* ************************************************************************* * * CPU_init_critical registers * * setup important registers * setup memory timing * ************************************************************************* */ cpu_init_crit: //cpu的初始化,是xload启动uboot前需要完成的内容 /* * Invalidate L1 I/D */ mov r0, #0 /* set up for MCR */ mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ mcr p15, 0, r0, c7, c5, 1 /* invalidate icache */ /* Invalide L2 cache (gp device call point) * - warning, this may have issues on EMU/HS devices * this call can corrupt r0-r5 */ mov r12, #0x1 @ set up to invalide L2 smi: .word 0xE1600070 @ Call SMI monitor /* * disable MMU stuff and caches */ 。。。。。。。。。。。。 #ifndef CONFIG_ICACHE_OFF orr r0, r0, #0x00001800 @ set bit 11,12 (---I Z---) BTB,I-Cache #endif mcr p15, 0, r0, c1, c0, 0 /* * Jump to board specific initialization... The Mask ROM will have already initialized * basic memory. Go here to bump up clock rate and handle wake up conditions. */ 。。。。。。。。。。。。 bl lowlevel_init /* go setup pll,mux,memory */ //这里比较重要,是我问题的核心所在,因为这里会跳入另一个汇编文件 platform.s中,如下 { .globl lowlevel_init lowlevel_init: ldr sp, SRAM_STACK str ip, [sp] /* stash old link register */ mov ip, lr /* save link reg across call */ bl s_init /* go setup pll,mux,memory */ //在这里BL跳入c语言omap3530beagle.c中去,因此这里的调用比较隐蔽,是汇编和C的交互 一般在汇编后形成函数的未解决符号表和导出符号表,不同编译器和语言形成的符号格式有所不同。在链接阶段完成程序的链接,当然这里属于静态过程) ldr ip, [sp] /* restore save ip */ mov lr, ip /* restore link reg */ /* back to arch calling code */ mov pc, lr /* the literal pools origin */ .ltorg 。。。} mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ /* * exception handler */ .align 5 do_hang: ldr sp, _TEXT_BASE /* use 32 words abort stack */ bl hang /* hang and never return */ //这是这段汇编出现异常时的反映,会跳入c语言中的hang函数。下面我们来看s_init函数:
int s_init(int skip) { u32 rev; rev = get_cpu_rev(); watchdog_init(); try_unlock_sram(); muxSetupAll(); delay(100); prcm_init(); config_3430sdram_ddr() 。。。。。。。 return(0); }
这也是我起初没有看到的问题,因为按道理这部分是必须先于board.c的start_armboot函数,毕竟是CPU,看门狗和sdram等的初始化。
在函数prcm_init中有如下部分代码:
if (beagle_revision() == REVISION_XM) { sr32(CM_CLKSEL3_PLL, 0, 5, CORE_DPLL_PARAM_M2); /* set M2 */ sr32(CM_CLKSEL2_PLL, 8, 11, CORE_DPLL_PARAM_M); /* set m */ sr32(CM_CLKSEL2_PLL, 0, 7, CORE_DPLL_PARAM_N); /* set n */ } else { sr32(CM_CLKSEL3_PLL, 0, 5, dpll_param_p->m2); /* set M2 */ sr32(CM_CLKSEL2_PLL, 8, 11, dpll_param_p->m); /* set m */ sr32(CM_CLKSEL2_PLL, 0, 7, dpll_param_p->n); /* set n */ }在这里可以看到,beagle_revsion的返回数值为2会进入else,这也是引起后续程序bug的主要原因,因为这里是针对Beagleboard-xm的基础时钟PLL的配置。出错以至于后续的各个模块都不能正常工作。
而在config_3430sdram_ddr函数中,会对sdram的大小进行判别如下:
if (beagle_revision() == REVISION_XM) { if (identify_xm_ddr() == MICRON_DDR) { __raw_writel(0x2, SDRC_CS_CFG); /* 256MB/bank */ __raw_writel(SDP_SDRC_MDCFG_0_DDR_MICRON_XM, SDRC_MCFG_0); __raw_writel(SDP_SDRC_MDCFG_0_DDR_MICRON_XM, SDRC_MCFG_1); __raw_writel(MICRON_V_ACTIMA_200, SDRC_ACTIM_CTRLA_0); __raw_writel(MICRON_V_ACTIMB_200, SDRC_ACTIM_CTRLB_0); __raw_writel(MICRON_V_ACTIMA_200, SDRC_ACTIM_CTRLA_1); __raw_writel(MICRON_V_ACTIMB_200, SDRC_ACTIM_CTRLB_1); __raw_writel(SDP_3430_SDRC_RFR_CTRL_200MHz, SDRC_RFR_CTRL_0); __raw_writel(SDP_3430_SDRC_RFR_CTRL_200MHz, SDRC_RFR_CTRL_1); } else { __raw_writel(0x4, SDRC_CS_CFG); /* 512MB/bank */ __raw_writel(SDP_SDRC_MDCFG_0_DDR_NUMONYX_XM, SDRC_MCFG_0); __raw_writel(SDP_SDRC_MDCFG_0_DDR_NUMONYX_XM, SDRC_MCFG_1); __raw_writel(NUMONYX_V_ACTIMA_165, SDRC_ACTIM_CTRLA_0); __raw_writel(NUMONYX_V_ACTIMB_165, SDRC_ACTIM_CTRLB_0); __raw_writel(NUMONYX_V_ACTIMA_165, SDRC_ACTIM_CTRLA_1); __raw_writel(NUMONYX_V_ACTIMB_165, SDRC_ACTIM_CTRLB_1); __raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_0); __raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_1); } } else { __raw_writel(0x1, SDRC_CS_CFG); /* 128MB/bank */ __raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_0); __raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_1); __raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_0); __raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_0); __raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_1); __raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_1); __raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_0); __raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_1); }
beagle_revision() == REVISION_XM
这句代码,很重要,也很bug,因为前面函数返回的数值在缺少那个补丁时返回2,后者默认是0,当然不会进行512M的sdram配置处会对后续的uboot造成影响。
。
总结,因此前期xload不能正常启动原因已经彻底定位到s_init中,未完成cpu时钟正常的初始化和sdram初始化,而不是start_armboot函数中。故REVSION_XM=2是最好的解决方法。