Chinaunix首页 | 论坛 | 博客
  • 博客访问: 82845
  • 博文数量: 28
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-04 11:06
文章分类

全部博文(28)

文章存档

2014年(22)

2013年(5)

2012年(1)

我的朋友

分类: 嵌入式

2014-04-18 14:22:33

1。第一阶段完成的功能

u-boot-2010.06/arch/arm/cpu/arm920t/start.S
Bootloader第一阶段的功能
<1>硬件初始化。
   关WATCHDOG、关中断
  设置CPU工作模式为管理模式(svc)
  设置时钟频率 FCLK,HCLK,PCLK的比例(即设置CLKDIVN)
   RAM初始化 关闭MMU.CACHE
<2>为加载Bootloader的第二阶段代码准备RAM空间。
  所谓准备RAM空间就是初始化内存芯片,使其能正常工作。在start.S中调用lowlevel_init 函数来设置存储控制器,使得外接的SDRAM可用。代码在lowlevel_init.S中。
<3>设置好栈。
<4>跳转到第二阶段的C入口点。
  在跳转之前,还要清除BSS段(初始值为0、无初始化的全局变量、静态变量都放在BSS段)。如果设置了如下命令(1-bootdelay、2-bootm)则直接跳转,调用lib_arm/board.c中的start_armboot()函数。这是第二阶段的入口点。



start_code:

点击(此处)折叠或打开

  1.  .globl _start // uboot的主入口
  2. _start:    b    start_code //这是跳转向量表 占一个word
  3. ldr    pc, _undefined_instruction
  4. ldr    pc, _software_interrupt
  5. ldr    pc, _prefetch_abort
  6. ldr    pc, _data_abort
  7. ldr    pc, _not_used
  8. ldr    pc, _irq //中断向量
  9. ldr    pc, _fiq //中断向量

  10. //.word 伪操作用于分配一word的内存单元
  11. //并且用expr初始化 与.long作用相同
  12. _undefined_instruction:    .word undefined_instruction
  13. _software_interrupt:    .word software_interrupt
  14. _prefetch_abort:    .word prefetch_abort
  15. _data_abort:     .word data_abort
  16. _not_used:     .word not_used
  17. _irq:     .word irq
  18. _fiq:     .word fiq
  19. //以上总共占了4*7+4*8=60字节内存
  20. // .align伪操作用于表示对齐方式:通过添加填充字节使当前位置满足一定的对齐方式。.balign的作用
  21. .align。
  22. // .align {alignment} {,fill} {,max}
  23. // 其中:alignment用于指定对齐方式,可能的取值为2的次幂,缺省为4。fill是填充内容,缺省用0
  24. 填充。max是填充字节数最大值
  25. // .align 4 /* 指定对齐方式为字对齐 */ 
  26. .balignl 16,0xdeadbeef
  27. //16字节对齐 当指针移到64时填充0xdeadbeef这个值
  28. //不能为4,因为pc值在任何时候,都是4的倍数,只要不为0就为4的倍数,呵呵,这个值不行,如果用了这个值,0xdeadbeef永远也插不进去,呵呵。

  29. // TEXT_BASE在研发板相关的目录中的config.mk文档中定义, 他定义了
  30. // 代码在运行时所在的地址, 那么_TEXT_BASE中保存了这个地址

  31.  _TEXT_BASE:
  32. .word    TEXT_BASE

  33. //声明为全局变量 _armboot_start并用_start来初始化
  34. .globl _armboot_start
  35. _armboot_start:
  36. .word _start

  37. .globl _bss_start
  38. _bss_start:
  39. .word __bss_start

  40. .globl _bss_end
  41. _bss_end:

  42. .word _end
  43. #ifdef CONFIG_USE_IRQ
  44. /* IRQ stack memory (calculated at run-time) */
  45. .globl IRQ_STACK_START
  46. IRQ_STACK_START:
  47. .word    0x0badc0de

  48. /* IRQ stack memory (calculated at run-time) */
  49. .globl FIQ_STACK_START
  50. FIQ_STACK_START:
  51. .word 0x0badc0de
  52. #endif




start_code:
设置cpu的模式

点击(此处)折叠或打开

  1. /* set the cpu to SVC32 mode*/
  2. mrs    r0, cpsr
  3. bic    r0, r0, #0x1f
  4. orr    r0, r0, #0xd3
  5. msr    cpsr, r0
#ifdef CONFIG_S3C24X0
设置watchdog interupt clock divisor 的base 

点击(此处)折叠或打开

  1. # if defined(CONFIG_S3C2400)
  2. # define pWTCON    0x15300000
  3. # define INTMSK    0x14400008    /* Interupt-Controller base addresses */
  4. # define CLKDIVN    0x14800014    /* clock divisor register */
  5. #else
  6. # define pWTCON    0x53000000 // WatchDog-Controller base addresses
  7. # define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
  8. # define INTSUBMSK    0x4A00001C
  9. # define CLKDIVN    0x4C000014    /* clock divisor register */
  10. # endif

关看门狗

点击(此处)折叠或打开

  1. ldr    r0, =pWTCON
  2. mov    r1, #0x0
  3. str    r1, [r0]
关闭中断

点击(此处)折叠或打开

  1. mov    r1, #0xffffffff
  2. ldr    r0, =INTMSK
  3. str    r1, [r0]

  4. # if defined(CONFIG_S3C2410)
  5. ldr    r1, =0x3ff
  6. ldr    r0, =INTSUBMSK
  7. str    r1, [r0]
  8. # endif
  9. # if defined(CONFIG_S3C2440)
  10. ldr    r1, =0x7fff
  11. ldr    r0, =INTSUBMSK
  12. str    r1, [r0]
  13. # endif


#if 0
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
时钟设置在clock_init函数中
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
#endif /* CONFIG_S3C24X0 */

CPU初始化  关闭MMU Cache  并初始化存储控制器的参数 

点击(此处)折叠或打开

  1. #ifndef CONFIG_SKIP_LOWLEVEL_INIT
  2. bl    cpu_init_crit
  3. #endif
  4. //跳入cpu_init_crit ,这是一个系统初始化函数,他还会调用board/samsung/lowlevel_init.S中的lowlevel_init函数。主要是对系统总线的初始化,初始化了连接存储器的位宽、速度、刷新率等重要参数。经过这个函数的正确初始化,Nor Flash、SDRAM才可以被系统使用。下面的代码重定向就依赖它。
  5. lowlevel_init.S这个函数中要注意这时的代码、数据都只是保存在Nor Flash上,内存中还没有,所以读取数据时要变化数据。这些都在4kb Stepping Stone中进行。

    点击(此处)折叠或打开

    1. _TEXT_BASE:
    2.     .word    TEXT_BASE

    3. .globl lowlevel_init
    4. lowlevel_init:
    5.     /* memory control configuration */
    6.     /* make r0 relative the current location so that it */
    7.     /* reads SMRDATA out of FLASH rather than memory ! */
    8.     ldr r0, =SMRDATA  //SMRDATA 表示这13个寄存器的值存放的开始地址(连接地址),值为0x33F8 XXXX                                    ,处于内存中
    9.     ldr    r1, _TEXT_BASE  //代码段地址 0x33F8 0000,定义在board/samsung/smdk2440/config.mk中
    10.     sub    r0, r0, r1 //0x33F8 xxxx  与 0x33F8 0000相减,这就是13个寄存器值在NOR Flash上存放的地址
    11.     ldr    r1, =BWSCON    /* Bus Width Status Controller */
    12.     add r2, r0, #13*4
    13. 0:
    14.     ldr r3, [r0], #4
    15.     str r3, [r1], #4
    16.     cmp r2, r0
    17.     bne 0b

    18.     /* everything is fine now */
    19.     mov    pc, lr

    20.     .ltorg
    21. /* the literal pools origin */

    22. SMRDATA://根据SDRAM的datasheet,给13个寄存器赋值
    23.     .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    24.     .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    25.     .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    26.     .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    27.     .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    28.     .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    29.     .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    30.     .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    31.     .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    32.     .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    33.     .word 0x32
    34.     .word 0x30
    35.     .word 0x30

将堆栈前移并 初始化 因为clock_init(c code)需要

点击(此处)折叠或打开

  1. stack_setup:
  2. ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot     */
  3. sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area 代码段下面,留一段内存以实现malloc*/
  4. sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo  *///再留出一段内存,存一些全局参数
  5. #ifdef CONFIG_USE_IRQ  //IRQ,FIQ模式的栈
  6. sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
  7. #endif  
  8. sub sp, r0, #12     /* leave 3 words for abort-stack     *///最后,留出12字节的内存给abort异常

 时钟初始化函数
 bl  clock_init   

点击(此处)折叠或打开

  1. static inline void delay (unsigned long loops)
  2. {
  3.     __asm__ volatile ("1:\n"
  4.       "subs %0, %1, #1\n"
  5.       "bne 1b":"=r" (loops):"0" (loops));
  6. }

  7. /* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)
  8.  * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
  9.  */
  10. #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
  11. #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
  12. #define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
  13. #define S3C2440_UPLL_96MHZ ((0x38<<12)|(0x02<<4)|(0x01))
  14. #define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
  15. #define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
  16. #define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */
  17. #define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */

  18. /* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)
  19.  * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
  20.  */
  21. #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
  22. #define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))
  23. #define S3C2410_CLKDIV 0x03 /* FCLK:HCLK:PCLK = 1:2:4 */
  24. void clock_init(void)
  25. {
  26.     struct s3c24x0_clock_power *clk_power = (struct s3c24x0_clock_power *)0x4C000000;

  27.     /* support both of S3C2410 and S3C2440, by www.arm9.net */
  28.     if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
  29.     {
  30.         /* FCLK:HCLK:PCLK = 1:2:4 */
  31.         clk_power->CLKDIVN = S3C2410_CLKDIV;

  32.         /* change to asynchronous bus mod */
  33.         __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
  34.                     "orr r1, r1, #0xc0000000\n" /* Asynchronous */
  35.                     "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
  36.                     :::"r1"
  37.                     );
  38.         
  39.         /* to reduce PLL lock time, adjust the LOCKTIME register */
  40.         clk_power->LOCKTIME = 0xFFFFFFFF;

  41.         /* configure UPLL */
  42.         clk_power->UPLLCON = S3C2410_UPLL_48MHZ;

  43.         /* some delay between MPLL and UPLL */
  44.         delay (4000);

  45.         /* configure MPLL */
  46.         clk_power->MPLLCON = S3C2410_MPLL_200MHZ;

  47.         /* some delay between MPLL and UPLL */
  48.         delay (8000);
  49.     }
  50.     else
  51.     {
  52.         /* FCLK:HCLK:PCLK = 1:4:8 */
  53.         clk_power->CLKDIVN = S3C2440_CLKDIV;

  54.         /* change to asynchronous bus mod */
  55.         __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
  56.                     "orr r1, r1, #0xc0000000\n" /* Asynchronous */
  57.                     "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
  58.                     :::"r1"
  59.                     );

  60.         /* to reduce PLL lock time, adjust the LOCKTIME register */
  61.         clk_power->LOCKTIME = 0xFFFFFFFF;

  62.         /* configure UPLL */
  63.         clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

  64.         /* some delay between MPLL and UPLL */
  65.         delay (4000);

  66.         /* configure MPLL */
  67.         clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

  68.         /* some delay between MPLL and UPLL */
  69.         delay (8000);
  70.     }
  71. }

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
支持从nandFlash启动并判断启动方式

点击(此处)折叠或打开

  1. relocate:     /* relocate U-Boot to RAM     */
  2. adr    r0, _start     /* r0 <- current position of code *//R0:当前代码段开始地址
  3. ldr    r1, _TEXT_BASE     /* test if we run from flash or RAM *///R1:代码段的连接地址
  4. cmp    r0, r1     /* don't reloc during debug */ //测试现在是在Flash中还是在RAM中
  5. beq     clear_bss //stack_setup 如果是则直接跳转到 stack中

  6. ldr    r2, _armboot_start //
  7. ldr    r3, _bss_start
  8. sub    r2, r3, r2     /* r2 <- size of armboot *
  9. //主要是将c代码段(bootloader第二段)拷到 r1 即代码段链接地址中去
  10. //支持从nandflash启动并判断
  11. #if 1
  12. bl CopyCode2Ram
  13. #endif

  14. 点击(此处)折叠或打开

    1. int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
    2. {
    3.     unsigned int *pdwDest;
    4.     unsigned int *pdwSrc;
    5.     int i;

    6.     if (bBootFrmNORFlash())
    7.     {
    8.         pdwDest = (unsigned int *)buf;
    9.         pdwSrc = (unsigned int *)start_addr;
    10.         /* 从 NOR Flash启动 */
    11.         for (i = 0; i < size / 4; i++)
    12.         {
    13.             pdwDest[i] = pdwSrc[i];
    14.         }
    15.         return 0;
    16.     }
    17.     else
    18.     {
    19.         /* 初始化NAND Flash */
    20.         nand_init_ll();
    21.         /* 从 NAND Flash启动 */
    22.         nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));
    23.         return 0;
    24.     }
    25. }

    26. int bBootFrmNORFlash(void)
    27. {
    28.     volatile unsigned int *pdw = (volatile unsigned int *)0;
    29.     unsigned int dwVal;
    30.     
    31.     /*
    32.      * 无论是从NOR Flash还是从NAND Flash启动,
    33.      * 地址0处为指令"b    Reset", 机器码为0xEA00000B,
    34.      * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
    35.      * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
    36.      * 对于NOR Flash,必须通过一定的命令序列才能写数据,
    37.      * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
    38.      * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
    39.      */

    40.     dwVal = *pdw;
    41.     *pdw = 0x12345678;
    42.     if (*pdw != 0x12345678)
    43.     {
    44.         return 1;
    45.     }
    46.     else
    47.     {
    48.         *pdw = dwVal;
    49.         return 0;
    50.     }
    51. }


#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

清bss段

点击(此处)折叠或打开

  1. bic    sp, sp, #7     /* 8-byte alignment for ABI compliance */
  2.    
  3. clear_bss:
  4. ldr    r0, _bss_start     /* find start of bss segment */
  5. ldr    r1, _bss_end     /* stop here */
  6. mov    r2, #0x00000000     /* clear */

  7. clbss_l:str    r2, [r0]     /* clear loop... */
  8. add    r0, r0, #4
  9. cmp    r0, r1
  10. ble    clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot




阅读(1307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~