第一阶段:探索启动代码

首先进入/cpu/arm920t/start.S

6.2.1 关闭AT9200写的LED跳转

    orr     r0,r0,#0xd3
    msr    cpsr,r0

    #bl    coloured_LED_init
    #bl    red_LED_on
#ifdef  CONFIG_MINI2440_LED
  bl MINI2440_LED_on
#endif

6.2.2 修改CPU频率初始化设置

  2410和2440想必一个不同的地方就是PLL的初始化参数不一样,。这里一开始就讲频率提升到405MHz。其中还包括中断掩码的修正。

@ u-boot-2010.03/cpu/arm920t/start.S

    bne    copyex
#endif

#if defined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
    /*  turn off watchdog */

#if defined(CONFIG_S3C2400)
#define INTSUBMSK    0x4A00001C
#define CLKDIV           0x4C000014
#endif

#define MDIV_405      (0x7f<<12)
#define PSDIV_405     (2<<4)|(1<<0)
#define MDIV_200      (0xA1<<12)
#define PSDIV_200     (3<<4)|(1<<0)

    ldr    r0,=pWTCON
    mov r1,#0x0
    str    r0,[r1]

    ldr  r0, = INTMSK
    ldr  r1,[r0]

6.2.3 修改lowlevel_init.S文件

  为了匹配mini2440的存储器配置,需要修改lowlevel_init.S文件。这个所连接的NorFlash位数有关。置于SDRAM的参数,可以从芯片手册查到。SDRAM参数相关就是在这里修改的。

 

6.2.4 修改代码重定向部分

  Tekkaman Ninja从2009.08开始就在启动时增加了启动时检测自身是否已经在SDRAM中,已经芯片是NorBoot还是NandBoot的机制,来决定代码重定向的方式,是的编译出的bin文件可以同时烧入Nand Flash和Nor Flash,以及OpenJTAG载入进行调试。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif

/***************Check code position*************************/
    adr    r0,_start
    ldr     r1,TEXT_BASE
    cmp  r0,r1
    beq   stack_setup
    
/**************Check boot flash****************************/
    ldr    r0,=((4<<28)|(3<<4)|(3<<2))        /* address of Internal SRAM 0x4000003C */
    mov r1,#0
    str    r1,[r0]

    mov r1,#0x3C
    ldr    r0,[r1]
    cmp r0,#0
    bne  recolate

    /* recovery */
    ldr    r0,=(0xdeadbeef)
    ldr    r1,=((4<<28)|(3<<4)|(3<<2))
    str    r0,[r1]
    
/*************Nand Boot**********************************/
#define LENGTH_UBOOT    0x60000
#define NAND_CTL_BASE   0x4E000000
    
#ifdef CONFIG_S3C2440
#define oNFCONF    0x00
#define oNFCONT    0x04
#define oNFCMD      0x08
#define oNFSTAT     0x20

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

    .......

    ldr      r2,[r1,#oNFCONT]
    orr      r2,r2,#0x2
    str      r2,[#oNFCONT]

    ldr      sp,DW_STACK_START
    mov   fp,#0

    ldr      r0,=TEXT_BASE
    mov   r1,#0x0
    mov   r2,#LENGTH_UBOOT
    bl       nand_read_ll
    tst      r0,#0x0
    beq     ok_nand_read
    
bad_nand_read:
loop2:
    b    loop2

ok_nand_read:
    mov    r0,#0
    ldr       r1,=TEXT_BASE
    mov    r2,#0x400

go_next:
    ldr      r3,[r0],#4
    ldr      r4,[r1],#4
    teq     r3,r4
    bne    nomatch
    subs   r2,r2,#4
    beq     stack_setup
    bne  go_next

nomatch:
loop3:
    b    loop3
#endif

/***************Nor Flash***************************/
relocate:
  /************check for magic number *************/
  ldr  r1,=0xdeadbeef
  cmp  r0,r1
  bne  loop3

  adr  r0,_start
  ldr  r1,_TEXT_BASE
  ldr  r2,_armboot_start
  ldr  r3,_bss_start
  sub  r2,r3,r2
  add  r2,r0,r2

copy_loop:
  ldmia r0!,{r3-r10}
  stmia r1!,{r3-r10}
  cmp  r0,r2
  ble  copy_loop

......
#define STACK_BASE  0x33f00000
#define STACK_SIZE  0x10000
  .align
DW_STACK_STACK
  .word  STACK_BASE + STACK_SIZE - 4

  在上面添加的代码有一个跳转:bl nand_read_ll,它跳入是新增的C语言文件(/board/Samsung/mini2440/nand_read.c)中的函数,这个文件原本是vivi的代码,经过修改,并支持不同的Nand Flash芯片。

1 #include <common.h>
  2 #include <linux/mtd/nand.h>
  3 
  4 #define __REGb(x)    (*(volatile unsigned char *)(x))
  5 #define __REGw(x)    (*(volatile unsigned short *)(x))
  6 #define __REGi(x)    (*(volatile unsigned int *)(x))
  7 #define NF_BASE        0x4e000000
  8 #if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
  9 #define NFCONF        __REGi(NF_BASE + 0x0)
 10 #define NFCONT        __REGi(NF_BASE + 0x4)
 11 #define NFCMD        __REGb(NF_BASE + 0x8)
 12 #define NFADDR        __REGb(NF_BASE + 0xc)
 13 #define NFDATA        __REGb(NF_BASE + 0x10)
 14 #define NFDATA16    __REGw(NF_BASE + 0x10)
 15 #define NFSTAT        __REGb(NF_BASE + 0x20)
 16 #define NFSTAT_BUSY    1
 17 #define nand_select()    (NFCONT &= ~(1 << 1))
 18 #define nand_deselect()    (NFCONT |= (1 << 1))
 19 #define nand_clear_RnB()    (NFSTAT |= (1 << 2))
 20 #endif
 21 
 22 static inline void nand_wait(void)
 23 {
 24     int i;
 25  
 26     while (!(NFSTAT & NFSTAT_BUSY))
 27         for (i=0; i<10; i++);
 28 }
 29  
 30 struct boot_nand_t {
 31     int page_size;
 32     int block_size;
 33     int bad_block_offset;
 34 };
 35  
 36 static int is_bad_block(struct boot_nand_t * nand, unsigned long i)
 37 {
 38     unsigned char data;
 39     unsigned long page_num;
 40  
 41     nand_clear_RnB();
 42     page_num = i >> 11; /* addr / 2048 */
 43     NFCMD = 0x00;    /*Read Command*/
 44     NFADDR = nand->bad_block_offset & 0xff;
 45     NFADDR = (nand->bad_block_offset >> 8) & 0xff;
 46     NFADDR = page_num & 0xff;
 47     NFADDR = (page_num >> 8) & 0xff;
 48     NFADDR = (page_num >> 16) & 0xff;
 49     NFCMD = 0x70;    /*Read Status Command*/
 50     nand_wait();
 51     data = (NFDATA & 0xff);
 52     if (data != 0xff)    /*If First Byte is Not 0xFF, Current Block is Bad*/
 53         return 1;
 54  
 55     return 0;
 56 }
 57 
 58 static int nand_read_page_ll(struct boot_nand_t * nand, unsigned char *buf, 
 59 unsigned long addr)
 60 {
 61     unsigned short *ptr16 = (unsigned short *)buf;
 62     unsigned int i, page_num;
 63     nand_clear_RnB();
 64     NFCMD = 0x00;
 65     page_num = addr >> 11; /* addr / 2048 */    /*Page Address*/
 66     /* Write Address */
 67     NFADDR = 0;    /* Read Data Page by Page*/
 68     NFADDR = 0;
 69     NFADDR = page_num & 0xff;
 70     NFADDR = (page_num >> 8) & 0xff;
 71     NFADDR = (page_num >> 16) & 0xff;
 72     NFCMD = 0x30;
 73     nand_wait();
 74     for (i = 0; i < (nand->page_size>>1); i++)    /*Read Data in This Page*/
 75         {
 76         *ptr16 = NFDATA16;
 77         ptr16++;
 78         }
 79     return nand->page_size;
 80 }
 81  
 82 extern unsigned int dynpart_size[];
 83  
 84 /* low level nand read function */
 85 int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
 86 {
 87     int i, j;
 88     unsigned short nand_id;
 89     struct boot_nand_t nand;
 90  
 91     /* chip Enable */
 92     nand_select();
 93     nand_clear_RnB();
 94 
 95         for (i = 0; i < 10; i++)
 96         ;
 97  
 98     nand.page_size = 2048;
 99     nand.block_size = 128 * 1024;
100     nand.bad_block_offset = nand.page_size;
101 
102     //if ((start_addr & (nand.block_size-1)) || (size & ((nand.block_size-1))))
103         //return -1;    /* invalid alignment */
104  
105     for (i=start_addr; i < (start_addr + size);) {
106         if (i & (nand.block_size-1)== 0)/*i equals to the next block's initial address*/
107             {
108             if (is_bad_block(&nand, i) ||
109                 is_bad_block(&nand, i + nand.page_size)) {
110                 /* Bad block */
111                 i += nand.block_size;
112                 size += nand.block_size;
113                 continue;
114             }
115         }
116         j = nand_read_page_ll(&nand, buf, i);
117         i += j;
118         buf += j;
119     }
120  
121     /* chip Disable */
122     nand_deselect();
123  
124     return 0;
125 }    

 

在添加这个文件之后,记得要在Makefile里加上对这个文件的编译。

#修改board/Samsung/mini2440/Makefile
LIB = $(obj)lib$(board).a
#COBJS := sbc2410.o flash.o
COBJS := nand_read.o mini2440.o flash.o
SOBJS := lowlevel_init.o

SRCS := $(SOBJS:.o = .S) $(COBJS:.o = .c)

 

  到这里,启动的第一阶段就修改结束,但是在U-Boot-1.3.3之后,这些本应放在bin文件前4K的代码会被放到后面,以至启动失败。随意必须手动修改连接时使用的.lds文件,是的这些代码被放在bin文件的最前面。

#修改U-Boot-2010.03/cpu/arm920t/u-boot.lds

    .text:
    {
        cpu/arm920t/start.o
        board/Samsung/mini2440/lowlevel_init.o
        board/Samsung/mini2440/nand_read.o
    } 

 

posted @ 2016-07-01 17:15  pingfandfy  阅读(278)  评论(0编辑  收藏  举报