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部分文章。

 

posted @ 2016-09-14 16:28  达达kiki  阅读(200)  评论(0)    收藏  举报