从Nand Flash启动U-BOOT的基本原理

Cited from http://hi.baidu.com/zengzhaonong/blog/item/4b901ee9b5ef343cb90e2d16.html
前4K的问题
    如果S3C2410被配置成从Nand Flash启动(
配置由硬件工程师在电路板设置 ), S3C2410的Nand Flash控制器有一个特殊的功能,在S3C2410上电后,Nand Flash控制器会自动的把Nand Flash上的前4K数据搬移到4K内部RAM中,并把0x00000000设置内部RAM的起始地址,CPU从内部RAM的0x00000000位置开 始启动。这个过程不需要程序干涉。
    程序员需要完成的工作,是把最核心的启动程序放在Nand Flash的前4K中。
启动程序的安排
    由于Nand Flash控制器从Nand Flash中搬移到内部RAM的代码是有限的,所以在启动代码的前4K里,我们必须完成S3C2410的核心配置以及把启动代码(U-BOOT)剩余部分搬到RAM中运行。


    u-boot源码不支持从nand flash启动,可是s3c2410支持从nand flash启动,开发板(sbc-2410x)加电后s3c2410将nand flash的前4k(保存有u-boot的部分功能--拷贝功能--把nand flash中的内容拷贝到SDRAM)拷贝到sram(s3c2410芯片内的sram)。这就需要修改u-boot源码,增加u-boot的功能: 使u-boot在得到执行权后能够将其自身拷贝到开发板上SDRAM中,以便处理器能够执行u-boot。

# cd u-boot-1.1.6

在board/bks2410加入NAND Flash读函数,建立nand_read.c,加入如下内容(copy from vivi):
# vi board/sbc2410x/
nand_read.c
-----------------------------------------------
#include <config.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE   0x4e000000
#define NFCONF    __REGi(NF_BASE + 0x0)
#define NFCMD     __REGb(NF_BASE + 0x4)
#define NFADDR    __REGb(NF_BASE + 0x8)
#define NFDATA    __REGb(NF_BASE + 0xc)
#define NFSTAT    __REGb(NF_BASE + 0x10)

#define BUSY 1
inline void wait_idle(void) {
    int i;

    while(!(NFSTAT & BUSY))
        for(i=0; i<10; i++);
}

#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK   (NAND_SECTOR_SIZE - 1)

/* low level nand read function */
int nand_read_ll(unsigned char *buf, 
                unsigned long start_addr, 
                int            size)
{
    int i, j;

    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return -1; /* invalid alignment */
    }

    /* chip Enable */
    NFCONF &= ~0x800;
    for(i=0; i<10; i++);

    for(i=start_addr; i < (start_addr + size);) {
        /* READ0 */
        NFCMD = 0;

        /* Write Address */
        NFADDR = i & 0xff;
        NFADDR = (i >> 9) & 0xff;
        NFADDR = (i >> 17) & 0xff;
        NFADDR = (i >> 25) & 0xff;

        wait_idle();

        for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
            *buf = (NFDATA & 0xff);
            buf++;
        }
    }

    /* chip Disable */
    NFCONF |= 0x800; /* chip disable */

    return 0;
}



# vi board/sbc2410x/Makefile +28
-----------------------------------------------
COBJS   := sbc2410x.o flash.o        ==>
COBJS   := sbc2410x.o flash.o nand_read.o




# vi cpu/arm920t/start.S
-----------------------------------------------
从Nand Flash中把数据拷贝到RAM,是由copy_myself程序段完成
(1) 在"ldr pc, _start_armboot"之前加入(223行):
#ifdef CONFIG_S3C2410_NAND_BOOT
   bl     copy_myself

   @ jump to ram
   ldr    r1, =on_the_ram
   add    pc, r1, #0
   nop
   nop
   1:     b      1b           @ infinite loop

on_the_ram:
#endif


(2) 在"_start_armboot: .word start_armboot"之后加入:
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
   mov r10, lr
@ 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 1b
2:ldr   r2, [r1, #oNFSTAT]       @ wait ready
   tst r2, #0x1
   beq 2b
   ldr r2, [r1, #oNFCONF]
   orr r2, r2, #0x800          @ disable chip
   str r2, [r1, #oNFCONF]

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

@ copy vivi to RAM
   ldr    r0, =UBOOT_RAM_BASE
   mov    r1, #0x0
   mov    r2, #0x20000
   bl     nand_read_ll
   tst    r0, #0x0
   beq    ok_nand_read

#ifdef CONFIG_DEBUG_LL
   bad_nand_read:
   ldr    r0, STR_FAIL
   ldr    r1, SerBase
   bl     PrintWord
1:b       1b           @ infinite loop
   #endif

ok_nand_read:
#ifdef CONFIG_DEBUG_LL
   ldr    r0, STR_OK
   ldr    r1, SerBase
   bl     PrintWord
#endif

@ verify
   mov    r0, #0
   ldr    r1, =UBOOT_RAM_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    done_nand_read
   bne    go_next

notmatch:
#ifdef CONFIG_DEBUG_LL
   sub    r0, r0, #4
   ldr    r1, SerBase
   bl     PrintHexWord
   ldr    r0, STR_FAIL
   ldr    r1, SerBase
   bl     PrintWord
#endif
1:b       1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
   ldr    r0, STR_OK
   ldr    r1, SerBase
   bl     PrintWord
#endif
   mov    pc, r10
@ clear memory
@ r0: start address
@ r1: length
   mem_clear:
   mov r2, #0
   mov r3, r2
   mov r4, r2
   mov r5, r2
   mov r6, r2
   mov r7, r2
   mov r8, r2
   mov r9, r2

clear_loop:
   stmia r0!, {r2-r9}
   subs   r1, r1, #(8 * 4)
   bne    clear_loop
   mov    pc, lr

#endif @ CONFIG_S3C2410_NAND_BOOT


(3) 在文件的最后加入:
    .align      2
DW_STACK_START:
.word       STACK_BASE+STACK_SIZE-4





# vi include/configs/sbc2410x.h
-----------------------------------------------
(1) 将CONFIG_SERVERIP设置为主机IP
    这样以后在通过网络下载内核映像时,就不用就该IP地址了。(这一项修改与nand flash没有关系)

#define CONFIG_SERVERIP     192.168.0.240


(2) 在文件末尾添加如下内容
/*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE         0x33f00000
#define STACK_SIZE         0x8000
#define UBOOT_RAM_BASE     0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE      0x4E000000
#define bINT_CTL(Nb)       __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF            0x00
#define oNFCMD             0x04
#define oNFADDR            0x08
#define oNFDATA            0x0c
#define oNFSTAT            0x10
#define oNFECC             0x14

参考:

U-BOOT Nand
命令支持
 http://blogold.chinaunix.net/u1/47239/showart_376731.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值