Start.s详细分析3
当执行完第一阶段相关硬件初始化后我们开始设置堆栈,其实在这里,很容易有个疑问,就是为什么我们在执行c之前要设置堆栈,在网上看了一些资料,大致是这样说,通过栈来保存断点,当调用子程序完毕后能恢复到之前到该断点时的状态,比如r0、r1。
我们调用子程序会使得诸如r0、r1等寄存器被操作,因此如果在源程序段断点之后的操作需要断点之前的数据,那么就必须设置栈,下面是相关设定:
stack_setup: ldr r0, _TEXT_BASE sub r0, r0, #CFG_MALLOC_LEN sub r0, r0, #CFG_GBL_DATA_SIZE #ifdef CONFIG_USE_IRQ sub r0, r0, / #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12
上述的过程英文的称呼是Set up the stack ,设置栈,如果我们清楚的话那么其实就是根据要的保存的数据段,计算sp指针应该指向哪里,整个过程中实际并没有对整个栈的设定,只有sp指针的赋值,在设置断点后,通过对各个宏的索引很容易计算出sp最后指向的地址:0x33F3 DF74,于是设置好后我们才开始调用时钟初始化函数clock_init,内容如下(仅摘录有用部分):
1 S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000; 2 { 3 /* FCLK:HCLK:PCLK = 1:4:8 */ 4 clk_power->CLKDIVN = S3C2440_CLKDIV; 5 6 /* change to asynchronous bus mod */ 7 __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */ 8 "orr r1, r1, #0xc0000000\n" /* Asynchronous */ 9 "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */ 10 :::"r1" 11 ); 12 13 /* to reduce PLL lock time, adjust the LOCKTIME register */ 14 clk_power->LOCKTIME = 0xFFFFFFFF; 15 16 /* configure UPLL */ 17 clk_power->UPLLCON = S3C2440_UPLL_48MHZ; 18 19 /* some delay between MPLL and UPLL */ 20 delay (4000); 21 22 /* configure MPLL */ 23 clk_power->MPLLCON = S3C2440_MPLL_400MHZ; 24 25 /* some delay between MPLL and UPLL */ 26 delay (8000); 27 }
我们可以看到,分频部分相对2410示例源程序转移到了这里,同时还设定时钟相关参数,其中UPLL用于USB接口,MPLL用于CPU和其他外围部件,由MPLL及一些相关寄存器产生的FCLK、HCLK、PCLK设定后分别为硬件提供支持,因此可以联想到,如果需要在后续过程中用到USB、GPIO、LCD等硬件,在这里我们就必须设置好时钟,像这样把所有的时钟配置好便于为后续硬件添加提供支持。
接着是重定位过程,对应stage1中的“将u-boot代码复制到RAM”过程,过程中r0、r1、r2对应原始位置、需要拷贝到RAM中的起始位置、需要拷贝代码段的大小,在这里我们并没有在设置栈,猜测是因为这里本来就是将r0、r1、r2三者的数据传给子程序CopyCode2Ram使用,而不是像之前那样与子程序之间是独立的,代码如下:
{ unsigned int *pdwDest; unsigned int *pdwSrc; int i; if (bBootFrmNORFlash()) { pdwDest = (unsigned int *)buf; //0xff80 0000 pdwSrc = (unsigned int *)start_addr; //0x0 /* 从 NOR Flash启动 */ for (i = 0; i < size / 4; i++) //size 代码大小 { pdwDest[i] = pdwSrc[i]; //把指向0x0(Nor flash)代码 按照size大小 copy 到 0xff80 0000(开始) ~ 0xff80 0000 + size } return 0; } else { /* 初始化NAND Flash */ nand_init_ll(); /* 从 NAND Flash启动 */ nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP)); return 0; } }
这里提供了两种备选,从nor flash或者nand flash启动,初始化相关分析见2440部分文章。

浙公网安备 33010602011771号