bb-xm revc移植3 之 xload启动过程略解以及bug的彻底起因和解决

困惑于前面的博文中提到的xload启动的问题,这次仔细的看了一下,也从网上学习了一些xload的启动过程。

从内部的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是最好的解决方法。


你可能感兴趣的:(bb-xm revc移植3 之 xload启动过程略解以及bug的彻底起因和解决)