05
29

Porting U-BOOT for NAND booting in 2 days

開發環境: CentOS5
第一天早上(toolchain preparation and compile u-boot):
1.下載ELDK4.1
   我下載的版本是 arm-linux-x86-uclibc. 底下是它的連結.

      
ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86-uclibc/iso/arm-2007-01-22-uclibc-src.iso
2. Install ELDK4.1
     用指令“install –d directory [cpu family]”安裝ELDK. 舉例來說, 輸入 “install –d /usr/local/eldk arm”
3. 下載 並解壓縮U-BOOT 1.3.2
   
ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.2.tar.bz2
    輸入指令"tar jxvf u-boot-1.3.2.tar.bz2"
4. 編譯 U-BOOT 1.3.2
    進入 u-boot-1.3.2 的目錄, 輸入 “make smdk2410_config” 然候再輸入 “make all”
    I如果成功的話, 你會看到u-boot(elf image) 和u-boot.bin(binary  image)在u-boot的資料夾下
    


第一天中午(Let U-BOOT 1.3.2 start in ram)

1.讓u-boot在記憶體執行
   修改 u-boot/include/configs/smdk2410.h. 加入以下兩行
   #define CONFIG_SKIP_LOWLEVEL_INIT
   #define CONFIG_SKIP_RELOCATE_UBOOT
   修改 /u-boot/board/smdk2410/u-boot.lds
  
SECTIONS
  
{
        . =
0x00000000;

   變成如下(修改執行位址)
  
SECTIONS
  
{
        . =
0x33F80000;

   再編譯一次

2.準備debug工具
   下載toolchain
http://www.yagarto.de/#download
   下載完後安裝,開啟dos視窗並輸入arm-elf-insight看到如下畫面
 

3.用arm-elf-insight連結ICE的gdb server
   我用的是JLink(
http://www.segger.de/).
    

4. 讓u-boot在ram中執行
   輸入“arm-elf-insight u-boot”, 你可以看到u-boot source出現了
  
  
  下載u-boot image至 0x33f80000
 

  修改 PC(program counter) to 0x33f80000
 

 你可以單步執行或continue
 

 如果選擇"continue", 你會看到u-boot畫面已經出現在serial上了
 

 第二天早上(Let U-BOOT 1.3.2 start from NAND)
1. 加入NAND 開機碼 at /uboot/cpu/start.s
  底下是一個範例,請參考
 
/*
 *  armboot - Startup Code for ARM920 CPU-core
 *
 *  Copyright (c) 2001    Marius Gr鐷er <mag@sysgo.de>
 *  Copyright (c) 2002    Alex Zke <azu@sysgo.de>
 *  Copyright (c) 2002    Gary Jennejohn <gj@denx.de>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

 
 
#include <config.h>
#include <version.h>
#include <status_led.h>
 
/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

 
/*.equ BOOTFromNAND , 0 */ /*0 means you boot from ice*/
.
equ BWSCON       ,   0x48000000     /*Bus width & wait status*/
/*=================
 NAND flash
=================*/

.
equ NFCONF      ,    0x4e000000     /*NAND Flash configuration*/
.
equ NFCMD       ,    0x4e000004     /*NADD Flash command*/
.
equ NFADDR      ,    0x4e000008     /*NAND Flash address*/
.
equ NFDATA      ,    0x4e00000c     /*NAND Flash data*/
.
equ NFSTAT      ,    0x4e000010     /*NAND Flash operation status*/
.
equ NFECC       ,    0x4e000014     /*NAND Flash ECC*/
.
globl _start
_start:    b       start_code
    
ldr    pc, _undefined_instruction
    
ldr    pc, _software_interrupt
    
ldr    pc, _prefetch_abort
    
ldr    pc, _data_abort
    
ldr    pc, _not_used
    
ldr    pc, _irq
    
ldr    pc, _fiq
 
_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq
 
    .
balignl 16,0xdeadbeef
 
 
/*
 *************************************************************************
 *
 * Startup Code (called from the ARM reset exception vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */

 
_TEXT_BASE:
    .
word    TEXT_BASE
 
.
globl _armboot_start
_armboot_start:
    .
word _start
 
/*
 * These are defined in the board-specific linker script.
 */

.
globl _bss_start
_bss_start:
    .
word __bss_start
 
.
globl _bss_end
_bss_end:
    .
word _end
 
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.
globl IRQ_STACK_START
IRQ_STACK_START:
    .
word    0x0badc0de
 
/* IRQ stack memory (calculated at run-time) */
.
globl FIQ_STACK_START
FIQ_STACK_START:
    .
word 0x0badc0de
#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
 
    
bl coloured_LED_init
    
bl red_LED_on
 
#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
    
/*
     * relocate exception table
     */

    
ldr    r0, =_start
    
ldr    r1, =0x0
    
mov    r2, #16
copyex:
    
subs    r2, r2, #1
    
ldr    r3, [r0], #4
    
str    r3, [r1], #4
    
bne    copyex
#endif
 
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    
/* turn off the watchdog */
 
# if defined(CONFIG_S3C2400)
#  define pWTCON        0x15300000
#  define INTMSK        0x14400008    /* Interupt-Controller base addresses */
#  define CLKDIVN    0x14800014    /* clock divisor register */
#else
#  define pWTCON        0x53000000
#  define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
#  define INTSUBMSK    0x4A00001C
#  define CLKDIVN    0x4C000014    /* clock divisor register */
# endif
 
    
ldr     r0, =pWTCON
    
mov     r1, #0x0
    
str     r1, [r0]
 
    
/*
     * mask all IRQs by setting all bits in the INTMR - default
     */

    
mov    r1, #0xffffffff
    
ldr    r0, =INTMSK
    
str    r1, [r0]
# if defined(CONFIG_S3C2410)
    
ldr    r1, =0x3ff
    
ldr    r0, =INTSUBMSK
    
str    r1, [r0]
# endif
 
    
/* FCLK:HCLK:PCLK = 1:2:4 */
    
/* default FCLK is 120 MHz ! */
    
ldr    r0, =CLKDIVN
    
mov    r1, #3
    
str    r1, [r0]
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */
 
    
/*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    
bl    cpu_init_crit
#endif
 
#ifdef    CONFIG_AT91RM9200
 
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:                /* relocate U-Boot to RAM        */
    
adr    r0, _start        /* r0 <- current position of code   */
    
ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
    
cmp     r0, r1                  /* don't reloc during debug         */
    
beq     stack_setup
 
    
ldr    r2, _armboot_start
    
ldr    r3, _bss_start
    
sub    r2, r3, r2        /* r2 <- size of armboot            */
    
add    r2, r0, r2        /* r2 <- source end address         */
 
copy_loop:
    
ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */
    
stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */
    
cmp    r0, r2            /* until source end addreee [r2]    */
    
ble    copy_loop
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
    
/* Set up the stack                            */
stack_setup:
    
ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
    
sub    r0, r0, #CFG_MALLOC_LEN    /* malloc area                      */
    
sub    r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#ifdef CONFIG_USE_IRQ
    
sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    
sub    sp, r0, #12        /* leave 3 words for abort-stack    */
 
clear_bss:
    
ldr    r0, _bss_start        /* find start of bss segment        */
    
ldr    r1, _bss_end        /* stop here                        */
    
mov     r2, #0x00000000        /* clear                            */
 
clbss_l:str    r2, [r0]        /* clear loop...                    */
    
add    r0, r0, #4
    
cmp    r0, r1
    
ble    clbss_l
#ifdef NANDBOOT
/*For Nand Boot*/
    
ldr    r0, =BWSCON
    
ldr    r0, [r0]
    
ands    r0, r0, #6        /*OM[1:0] != 0, NOR FLash boot*/
    
bne    GoMain        /*do not read nand flash    */
    
    
mov    r5, #NFCONF
    
ldr    r0,    =(1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7)
    
str    r0,    [r5]
    
bl    ReadNandID
    
mov    r6, #0
    
ldr    r0, =0xec73
    
cmp    r5,    r0
    
beq    1f
    
ldr    r0, =0xec75
    
cmp    r5, r0
    
beq    1f
    
mov    r6, #1
1:   
    
bl    ReadNandStatus   
    
    
mov    r8, #0
    
/*ldr    r9, =__main    */
    
/*ldr r9,=0x33A00000*/
    
ldr r9,=TEXT_BASE
2:   
    
ands    r0, r8, #0x1f
    
bne        3f
    
mov        r0, r8
    
bl        CheckBadBlk
    
cmp        r0, #0
    
addne    r8, r8, #32
    
bne        4f
3:   
    
mov    r0, r8
    
mov    r1, r9
    
bl    ReadNandPage
    
add    r9, r9, #512
    
add    r8, r8, #1
4:   
    
cmp    r8, #400            /*524K*/
    
bcc    2b
    
    
mov    r5, #NFCONF            /*DsNandFlash*/
    
ldr    r0, [r5]
    
and    r0, r0, #~0x8000
    
str    r0, [r5]
    
ldr    pc, =GoMain
ReadNandID:
    
mov         r7,#NFCONF   
    
ldr      r0,[r7,#0]        /*NFChipEn();*/
    
bic      r0,r0,#0x800
    
str      r0,[r7,#0]   
    
mov      r0,#0x90        /*WrNFCmd(RdIDCMD);*/
    
strb     r0,[r7,#4]   
    
mov      r4,#0            /*WrNFAddr(0);*/
    
strb     r4,[r7,#8]   
1:                            /*while(NFIsBusy());*/
    
ldr      r0,[r7,#0x10]   
    
tst      r0,#1
    
beq      1b
    
ldrb     r0,[r7,#0xc]    /*id  = RdNFDat()<<8;*/
    
mov      r0,r0,lsl #8   
    
ldrb     r1,[r7,#0xc]    /*id |= RdNFDat();*/
    
orr      r5,r1,r0   
    
ldr      r0,[r7,#0]        /*NFChipDs();*/
    
orr      r0,r0,#0x800
    
str      r0,[r7,#0]   
    
mov         pc,lr   
    
ReadNandStatus:
    
mov         r7,#NFCONF
    
ldr      r0,[r7,#0]        /*NFChipEn();*/
    
bic      r0,r0,#0x800
    
str      r0,[r7,#0]
    
mov      r0,#0x70        /*WrNFCmd(QUERYCMD);*/
    
strb     r0,[r7,#4]   
    
ldrb     r1,[r7,#0xc]    /*r1 = RdNFDat();*/
    
ldr      r0,[r7,#0]        /*NFChipDs();*/
    
orr      r0,r0,#0x800
    
str      r0,[r7,#0]
    
mov         pc,lr
 
WaitNandBusy:
    
mov      r0,#0x70        /*WrNFCmd(QUERYCMD);*/
    
mov      r1,#NFCONF
    
strb     r0,[r1,#4]
1:                            /*while(!(RdNFDat()&0x40));    */
    
ldrb     r0,[r1,#0xc]
    
tst      r0,#0x40
    
beq           1b
    
mov      r0,#0            /*WrNFCmd(READCMD0);*/
    
strb     r0,[r1,#4]
    
mov      pc,lr
 
CheckBadBlk:
    
mov        r7, lr
    
mov        r5, #NFCONF
    
    
bic        r0, r0, #0x1f    /*addr &= ~0x1f;*/
    
ldr      r1,[r5,#0]        /*NFChipEn()*/
    
bic      r1,r1,#0x800
    
str      r1,[r5,#0]   
 
    
mov      r1,#0x50        /*WrNFCmd(READCMD2)*/
    
strb     r1,[r5,#4]   
    
mov         r1, #5
    
strb     r1,[r5,#8]        /*WrNFAddr(5)*/
    
strb     r0,[r5,#8]        /*WrNFAddr(addr)*/
    
mov      r1,r0,lsr #8    /*WrNFAddr(addr>>8)*/
    
strb     r1,[r5,#8]   
    
cmp      r6,#0            /*if(NandAddr)        */
    
movne    r0,r0,lsr #16    /*WrNFAddr(addr>>16)*/
    
strneb   r0,[r5,#8]
    
    
bl        WaitNandBusy    /*WaitNFBusy()*/
 
    
ldrb    r0, [r5,#0xc]    /*RdNFDat()*/
    
sub        r0, r0, #0xff
    
    
mov      r1,#0            /*WrNFCmd(READCMD0)*/
    
strb     r1,[r5,#4]   
    
    
ldr      r1,[r5,#0]        /*NFChipDs()*/
    
orr      r1,r1,#0x800
    
str      r1,[r5,#0]
    
    
mov        pc, r7
 
ReadNandPage:
    
mov         r7,lr
    
mov      r4,r1
    
mov      r5,#NFCONF
 
    
ldr      r1,[r5,#0]        /*NFChipEn()*/
    
bic      r1,r1,#0x800
    
str      r1,[r5,#0]   
 
    
mov      r1,#0            /*WrNFCmd(READCMD0)*/
    
strb     r1,[r5,#4]   
    
strb     r1,[r5,#8]        /*WrNFAddr(0)*/
    
strb     r0,[r5,#8]        /*WrNFAddr(addr)*/
    
mov      r1,r0,lsr #8    /*WrNFAddr(addr>>8)*/
    
strb     r1,[r5,#8]   
    
cmp      r6,#0            /*if(NandAddr)        */
    
movne    r0,r0,lsr #16    /*WrNFAddr(addr>>16)*/
    
strneb   r0,[r5,#8]
    
    
ldr      r0,[r5,#0]        /*InitEcc()*/
    
orr      r0,r0,#0x1000
    
str      r0,[r5,#0]   
    
    
bl       WaitNandBusy    /*WaitNFBusy()*/
    
    
mov      r0,#0            /*for(i=0; i<512; i++)*/
1:
    
ldrb     r1,[r5,#0xc]    /*buf[i] = RdNFDat()*/
    
strb     r1,[r4,r0]
    
add      r0,r0,#1
    
bic      r0,r0,#0x10000
    
cmp      r0,#0x200
    
bcc      1b
    
    
ldr      r0,[r5,#0]        /*NFChipDs()*/
    
orr      r0,r0,#0x800
    
str      r0,[r5,#0]
        
    
mov         pc,r7
#endif
GoMain:
    
ldr    pc, _start_armboot
 
_start_armboot:    .word start_armboot
 
 
/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */

 
 
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
    
/*
     * flush v4 I/D caches
     */

    
mov    r0, #0
    
mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
    
mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
 
    
/*
     * disable MMU stuff and caches
     */

    
mrc    p15, 0, r0, c1, c0, 0
    
bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
    
bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
    
orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
    
orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
    
mcr    p15, 0, r0, c1, c0, 0
 
    
/*
     * before relocating, we have to setup RAM timing
     * because memory timing is board-dependend, you will
     * find a lowlevel_init.S in your board directory.
     */

    
mov    ip, lr
#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
 
#else
    
bl    lowlevel_init
#endif
    
mov    lr, ip
    
mov    pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
 
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */

 
@
@
IRQ stack frame.
@
#define S_FRAME_SIZE    72
 
#define S_OLD_R0    68
#define S_PSR        64
#define S_PC        60
#define S_LR        56
#define S_SP        52
 
#define S_IP        48
#define S_FP        44
#define S_R10        40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0
 
#define MODE_SVC 0x13
#define I_BIT     0x80
 
/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

 
    .
macro    bad_save_user_regs
    
sub    sp, sp, #S_FRAME_SIZE
    
stmia    sp, {r0 - r12}            @ Calling r0-r12
    
ldr    r2, _armboot_start
    
sub    r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    
sub    r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
    
ldmia    r2, {r2 - r3}            @ get pc, cpsr
    
add    r0, sp, #S_FRAME_SIZE        @ restore sp_SVC
 
    
add    r5, sp, #S_SP
    
mov    r1, lr
    
stmia    r5, {r0 - r3}            @ save sp_SVC, lr_SVC, pc, cpsr
    
mov    r0, sp
    .
endm
 
    .
macro    irq_save_user_regs
    
sub    sp, sp, #S_FRAME_SIZE
    
stmia    sp, {r0 - r12}            @ Calling r0-r12
    
add     r7, sp, #S_PC
    
stmdb   r7, {sp, lr}^                   @ Calling SP, LR
    
str     lr, [r7, #0]                    @ Save calling PC
    
mrs     r6, spsr
    
str     r6, [r7, #4]                    @ Save CPSR
    
str     r0, [r7, #8]                    @ Save OLD_R0
    
mov    r0, sp
    .
endm
 
    .
macro    irq_restore_user_regs
    
ldmia    sp, {r0 - lr}^            @ Calling r0 - lr
    
mov    r0, r0
    
ldr    lr, [sp, #S_PC]            @ Get PC
    
add    sp, sp, #S_FRAME_SIZE
    
subs    pc, lr, #4            @ return & move spsr_svc into cpsr
    .
endm
 
    .
macro get_bad_stack
    
ldr    r13, _armboot_start        @ setup our mode stack
    
sub    r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
    
sub    r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
 
    
str    lr, [r13]            @ save caller lr / spsr
    
mrs    lr, spsr
    
str     lr, [r13, #4]
 
    
mov    r13, #MODE_SVC            @ prepare SVC-Mode
    @
msr    spsr_c, r13
    
msr    spsr, r13
    
mov    lr, pc
    
movs    pc, lr
    .
endm
 
    .
macro get_irq_stack            @ setup IRQ stack
    
ldr    sp, IRQ_STACK_START
    .
endm
 
    .
macro get_fiq_stack            @ setup FIQ stack
    
ldr    sp, FIQ_STACK_START
    .
endm
 
/*
 * exception handlers
 */

    .
align  5
undefined_instruction:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_undefined_instruction
 
    .
align    5
software_interrupt:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_software_interrupt
 
    .
align    5
prefetch_abort:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_prefetch_abort
 
    .
align    5
data_abort:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_data_abort
 
    .
align    5
not_used:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_not_used
 
#ifdef CONFIG_USE_IRQ
 
    .
align    5
irq:
    
get_irq_stack
    
irq_save_user_regs
    
bl     do_irq
    
irq_restore_user_regs
 
    .
align    5
fiq:
    
get_fiq_stack
    
/* someone ought to write a more effiction fiq_save_user_regs */
    
irq_save_user_regs
    
bl     do_fiq
    
irq_restore_user_regs
 
#else
 
    .
align    5
irq:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_irq
 
    .
align    5
fiq:
    
get_bad_stack
    
bad_save_user_regs
    
bl     do_fiq
 
#endif


2.    修改u-boot 1.3.2 的設定,讓它自NAND啟動
    修改 u-boot/include/configs/smdk2410.h. 把第一天我們加入的 “#define CONFIG_SKIP_LOWLEVEL_INIT” 註解掉
    修改 /u-boot/board/smdk2410/u-boot.lds
 
SECTIONS
{
        . =
0x00000000;
標籤: embedded
評論: 4 | 引用: 0 | 閱讀: 13376
  • 1 
Syungchi [ 2009-07-08 16:47 | 回覆 | 編輯 刪除 ]
該內容只有管理員可見
Joey [ 回復於2009-07-17 10:40 郵箱 | 編輯 刪除 ]
mount iso and get into the cdrom folder to execute command
Jam [ 2009-08-04 16:09 | 回覆 | 編輯 刪除 ]
該內容只有管理員可見
Joey [ 回復於2009-08-10 10:19 郵箱 | 編輯 刪除 ]
我沒透過j-tag寫nand flash...
  • 1 
發表評論
暱 稱: 密 碼:
網 址: E - mail:
驗證碼: 驗證碼圖片 選 項:
頭 像:
內 容: