Chinaunix首页 | 论坛 | 博客
  • 博客访问: 419899
  • 博文数量: 75
  • 博客积分: 2020
  • 博客等级: 大尉
  • 技术积分: 663
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-04 16:56
文章分类

全部博文(75)

文章存档

2010年(10)

2009年(65)

分类: LINUX

2009-09-16 09:49:24

大多数bootloader都分为stage1stage2两部分,u-boot也不例外。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

1Stage1 start.S代码结构

u-bootstage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:

1)定义入口。由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROMFlash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。

2)设置异常向量(Exception Vector)。

3)设置CPU的速度、时钟频率及终端控制寄存器。

4)初始化内存控制器。

5)将ROM中的程序复制到RAM中。

6)初始化堆栈。

7)转到RAM中执行,该工作可使用指令ldr pc来完成。

2Stage2 C语言代码部分

lib_arm/board.c中的start arm bootC语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-bootarmboot)的主函数,该函数只要完成如下操作:

1)调用一系列的初始化函数。

2)初始化Flash设备。

3)初始化系统内存分配函数。

4)如果目标系统拥有NAND设备,则初始化NAND设备。

5)如果目标系统有显示设备,则初始化该类设备。

6)初始化相关网络设备,填写IPMAC地址等。

7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。


修改/cpu/arm920t/start.S

(1)删除AT91RM9200使用的LED代码

#include

#include

#if defined(CONFIG_AT91RM9200DK)

#include     /*这是针对AT91RM9200DK开发板的*/

#endif

......

/*

 * the actual start code
 */

start_code:

    /*

     * set the cpu to SVC32 mode

     */

    mrs    r0,cpsr

    bic    r0,r0,#0x1f

orr    r0,r0,#0xd3

msr    cpsr,r0

#if defined(CONFIG_AT91RM9200DK)

    bl coloured_LED_init
    bl red_LED_on
#endif

 2)修改寄存器地址定义
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)

    /* turn off the watchdog */

#if defined(CONFIG_S3C2400)

#  define INTSUBMSK       0x4A00001C

#  define CLKDIVN     0x4C000014   /* clock divisor register */

# endif

#define CLK_CTL_BASE 0x4C000000

#define MDIV_405 0x7f << 12

#define PSDIV_405 0x21

#define MDIV_200 0xa1 << 12

#define PSDIV_200 0x31

#endif

......

3修改中断禁止部分

#if defined(CONFIG_S3C2410)

    ldr r1, =0x7ff /*根据2410芯片手册INTSUBMSK11位可用vivi 也是0x7ffUBoot一直没改过来。*/

    ldr r0, =INTSUBMSK

    str r1, [r0]

#endif

#if defined(CONFIG_S3C2440)

    ldr r1, =0x7fff /*根据2440芯片手册,INTSUBMSK15位可用*/

    ldr r0, =INTSUBMSK

    str r1, [r0]

#endif

4修改时钟设置(2440的主频为405MHz。)

# if defined(CONFIG_S3C2440)

    /* FCLK:HCLK:PCLK = 1:4:8 */

    ldr r0, =CLKDIVN

    mov r1, #5

    str r1, [r0]

  

    mrc p15, 0, r1, c1, c0, 0 /*read ctrl register */

    orr r1, r1, #0xc0000000 /*Asynchronous */

mcr p15, 0, r1, c1, c0, 0 /*write ctrl register*/

 

    /*now, CPU clock is 405.00 Mhz 这边直接copyvivi的部分代码*/
      
mov r1, #CLK_CTL_BASE  

       mov r2, #MDIV_405    

       add  r2, r2, #PSDIV_405     

       str    r2, [r1, #0x04]              /* MPLLCON tekkaman */

 

#else

    /* FCLK:HCLK:PCLK = 1:2:4 */

    /* default FCLK is 12 MHz ! 在这里u-boot有一个错误以为默认时钟为120MHz。其实如果没有添加以下设置FCLK的语句芯片内部的PLL是无效的FCLK 12MHzS3C24x0的芯片手册说得很明白。我一开始没有注意到这一点,是 CalmArrow提醒了我并和我讨论过,他也做过实验证实了这点。在这里对CalmArrow表示感谢和敬意*/
    ldr r0, =CLKDIVN
    mov r1, #3
    str r1, [r0]

    mrc p15, 0, r1, c1, c0, 0 /*read ctrl register tekkaman*/
    orr r1, r1, #0xc0000000 /*Asynchronous tekkaman*/
    mcr p15, 0, r1, c1, c0, 0 /*write ctrl register tekkaman*/

    /*now, CPU clock is 202.8 Mhz tekkaman*/
    mov r1, #CLK_CTL_BASE /* tekkaman*/
    mov r2, #MDIV_200 /* mpll_200mhz tekkaman*/
    add r2, r2, #PSDIV_200 /* mpll_200mhz tekkaman*/
    str r2, [r1, #0x04]

# endif
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

5将从Flash启动改成从NAND Flash启动。L177

#define LENGTH_UBOOT 0x60000

 

#ifdef CONFIG_S3C2440_NAND_BOOT

 

#define NAND_CTL_BASE 0x4E000000

/* Offset */

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFCMD 0x08

#define oNFSTAT 0x20

@#define LENGTH_UBOOT 0x60000

     @ reset NAND
    mov r1, #NAND_CTL_BASE
    ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
    str r2, [r1, #oNFCONF]
    ldr r2, [r1, #oNFCONF]

    ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
   str r2, [r1, #oNFCONT]
    ldr r2, [r1, #oNFCONT]

    ldr r2, =(0x6) @ RnB Clear
    str r2, [r1, #oNFSTAT]
    ldr r2, [r1, #oNFSTAT]
  
    mov r2, #0xff @ RESET command
    strb r2, [r1, #oNFCMD]

  mov r3, #0 @ wait
1:
  add r3, r3, #0x1
  cmp r3, #0xa
  blt 1

2:
  ldr r2, [r1, #oNFSTAT] @ wait ready
  tst r2, #0x4      @When RnB low to high transition is occurred, this value set
  beq 2


    ldr r2, [r1, #oNFCONT]
    orr r2, r2, #0x2 @ Flash Memory Chip Disable
    str r2, [r1, #oNFCONT]

@ get read to call C s (for nand_read())
  ldr sp, DW_STACK_START @ setup stack pointer
  mov fp, #0 @ no previous , so fp=0

@ copy U-Boot to RAM
  ldr r0, =TEXT_BASE
  mov r1, #0x0
  mov r2, #0x30000
  bl nand_read_ll
  tst r0, #0x0
  beq ok_nand_read

bad_nand_read:
loop2: b loop2 @ infinite loop


ok_nand_read:
@ verify
  mov r0, #0
  ldr r1, =TEXT_BASE
  mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
  ldr r3, [r0], #4
  ldr r4, [r1], #4
  teq r3, r4
  bne notmatch
  subs r2, r2, #4
  beq stack_setup
  bne go_next

notmatch:
loop3: b loop3 @ infinite loop

#endif @ CONFIG_S3C2440_NAND_BOOT

 #ifdef CONFIG_S3C2410_NAND_BOOT

#define NAND_CTL_BASE 0x4E000000

/* Offset */

#define oNFCONF 0x00

#define oNFCMD 0x04

#define oNFSTAT 0x10

@#define LENGTH_UBOOT 0x60000


 @ reset NAND
  mov r1, #NAND_CTL_BASE
  ldr r2, =0xf830 @ initial value
  str r2, [r1, #oNFCONF]
  ldr r2, [r1, #oNFCONF]
  bic r2, r2, #0x800 @ enable chip
  str r2, [r1, #oNFCONF]
  mov r2, #0xff @ RESET command
  strb r2, [r1, #oNFCMD]


  mov r3, #0 @ wait
1:
   add r3, r3, #0x1
  cmp r3, #0xa
  blt nand1

2:
  ldr r2, [r1, #oNFSTAT] @ wait ready
  tst r2, #0x1
  beq nand2

  ldr r2, [r1, #oNFCONF]
  orr r2, r2, #0x800 @ disable chip
  str r2, [r1, #oNFCONF]

@ get read to call C s (for nand_read())
  ldr sp, DW_STACK_START @ setup stack pointer
  mov fp, #0 @ no previous , so fp=0

@ copy U-Boot to RAM
  ldr r0, =TEXT_BASE
  mov r1, #0x0
  mov r2, #0x30000      //
还不知道为啥要由20000改成30000
  bl nand_read_ll
  tst r0, #0x0
  beq ok_nand_read

bad_nand_read:
loop2: b loop2 @ infinite loop


ok_nand_read:
@ verify
  mov r0, #0
  ldr r1, =TEXT_BASE
  mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
  ldr r3, [r0], #4
  ldr r4, [r1], #4
  teq r3, r4
  bne notmatch
  subs r2, r2, #4
  beq stack_setup
  bne go_next

notmatch:
loop3: b loop3 @ infinite loop

#endif @ CONFIG_S3C2410_NAND_BOOT

 

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

 relocate:                           /* relocate U-Boot to RAM       */

     adr   r0, _start        /* r0 <- current position of code   */

……

“ldr    pc, _start_armboot”之后加入:
#if defined(CONFIG_SMDK2440_LED)
#define GPIO_CTL_BASE 0x56000000
#define oGPIO_B 0x10
#define oGPIO_CON 0x0
/* R/W, Configures the pins of the port */
#define oGPIO_DAT 0x4
#define oGPIO_UP 0x8
/* R/W, Pull-up disable register */
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_B
    ldr    r2, =0x295551
    str    r2, [r1, #oGPIO_CON]
    mov    r2, #0xff
    str    r2, [r1, #oGPIO_UP]
    ldr    r2, =0x1c1
    str    r2, [r1, #oGPIO_DAT]
#endif

修改目的:如果看到只有LED1亮了,并响起蜂鸣器,说明UBoot的第一阶段已完成!(针对mini2440,若不是这块开发板的,必须修改或不添加)

 

  _start_armboot:    .word start_armboot  后加入:

#define STACK_BASE 0x33f00000

#define STACK_SIZE 0x10000

.align 2

DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

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