http://my.chinaunix.net/space.php?uid=24319701&do=blog&id=136249
在这篇中,我们将移植nand flash部分,支持NAND启动及NAND FLASH的读写访问。
首先,我们在u-boot-2010.12/include/configs/smdk2440.h中注销如下定义。
//#define CONFIG_ENV_IS_IN_FLASH 1
//#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
增加如下定义:
/*以下为NAND启动及驱动相关*/
#define CONFIG_S3C2440_NAND_BOOT 1
#define CONFIG_NAND_S3C2440
#define NAND_CTL_BASE 0x4E000000 //Nand Flash配置寄存器基地址,查2440手册可得知
#define oNFCONF 0x00 //相对Nand配置寄存器基地址的偏移量,还是配置寄存器的基地址
#define oNFCONT 0x04 //相对Nand配置寄存器基地址的偏移量,可得到控制寄存器的基地址(0x4E000004)
#define oNFADDR 0x0c //相对Nand配置寄存器基地址的偏移量,可得到地址寄存器的基地址(0x4E00000c)
#define oNFDATA 0x10 //相对Nand配置寄存器基地址的偏移量,可得到数据寄存器的基地址(0x4E000010)
#define oNFCMD 0x08 //相对Nand配置寄存器基地址的偏移量,可得到指令寄存器的基地址(0x4E000008)
#define oNFSTAT 0x20 //相对Nand配置寄存器基地址的偏移量,可得到状态寄存器的基地址(0x4E000020)
#define oNFECC 0x2c //相对Nand配置寄存器基地址的偏移量,可得到ECC寄存器的基地址(0x4E00002c)
#define UBOOT_LENGTH 0x40000 /*256K*/
#define STACK_BASE 0x33f00000 //定义堆栈的地址
#define STACK_SIZE 0x8000 //堆栈的长度大小
#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif
/* NAND flash settings */
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4E000000 //Nand配置寄存器基地址
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
//#define NAND_SAMSUNG_LP_OPTIONS 1 //注意:我们这里是64M的Nand Flash,所以不用,如果是128M的大块Nand Flash,则需加上
#endif
//添加环境变量保存到Nand的宏(注意:如果你要使用从Nor启动的saveenv命令,则不要这些Nand宏定义)
#define CONFIG_ENV_IS_IN_NAND 1
#define CONFIG_ENV_OFFSET 0x30000 //将环境变量保存到nand中的0x30000位置
#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
在arch/arm/cpu/arm920t/start.S文件中增加如下代码:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
//下面添加2440中u-boot从Nand Flash启动
#ifdef CONFIG_S3C2440_NAND_BOOT
mov r1, #NAND_CTL_BASE //复位Nand Flash
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF] //设置配置寄存器的初始值,参考s3c2440手册
ldr r2, [r1, #oNFCONF]
ldr r2, =( (1<<4)|(0<<1)|(1<<0) )
str r2, [r1, #oNFCONT] //设置控制寄存器
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) //RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff //复位command
strb r2, [r1, #oNFCMD]
mov r3, #0 //等待
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] //等待就绪
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 //取消片选
str r2, [r1, #oNFCONT]
//get read to call C functions (for nand_read())
ldr sp, DW_STACK_START //为C代码准备堆栈,DW_STACK_START定义在下面
mov fp, #0
//copy U-Boot to RAM
ldr r0, =CONFIG_SYS_LOAD_ADDR//传递给C代码的第一个参数:u-boot在RAM中的起始地址 //暂时为这个值
mov r1, #0x0 //传递给C代码的第二个参数:Nand Flash的起始地址
mov r2, #UBOOT_LENGTH //传递给C代码的第三个参数:u-boot的长度大小
bl nand_read_ll //此处调用C代码中读Nand的函数,现在还没有要自己编写实现
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2: b loop2 //infinite loop
ok_nand_read:
//检查搬移后的数据,如果前4k完全相同,表示搬移成功
mov r0, #0
ldr r1, =CONFIG_SYS_LOAD_ADDR//暂时为这个值
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 board_init_f
bne go_next
notmatch:
loop3: b loop3 //infinite loop
#endif //CONFIG_S3C2440_NAND_BOOT
.align 2 /*add by bsc 2010-2-6 13:11*/
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
增加从NAND FLASH读取数据到内存的函数,文件名为/nand_read.c放到board/samsung/smdk2440/nand_read.c下。
#include <config.h>
#define NF_BASE 0x4E000000 //Nand Flash配置寄存器基地址
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NFCONF __REGi(NF_BASE + 0x0 ) //通过偏移量还是得到配置寄存器基地址
#define NFCONT __REGi(NF_BASE + 0x4 ) //通过偏移量得到控制寄存器基地址
#define NFCMD __REGb(NF_BASE + 0x8 ) //通过偏移量得到指令寄存器基地址
#define NFADDR __REGb(NF_BASE + 0xC ) //通过偏移量得到地址寄存器基地址
#define NFDATA __REGb(NF_BASE + 0x10) //通过偏移量得到数据寄存器基地址
#define NFSTAT __REGb(NF_BASE + 0x20) //通过偏移量得到状态寄存器基地址
#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1)) //Nand片选使能
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1)) //取消Nand片选
#define NAND_CLEAR_RB (NFSTAT |= (1<<2))
#define NAND_DETECT_RB { while(! (NFSTAT&(1<<2)) );}
#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; //地址或长度不对齐
}
NAND_CHIP_ENABLE; //选中Nand片选
for(i=start_addr; i < (start_addr + size);)
{
//发出READ0指令
NAND_CLEAR_RB;
NFCMD = 0;
//对Nand进行寻址
NFADDR = i & 0xFF;
NFADDR = (i >> 9) & 0xFF;
NFADDR = (i >> 17) & 0xFF;
NFADDR = (i >> 25) & 0xFF;
NAND_DETECT_RB;
for(j=0; j < NAND_SECTOR_SIZE; j++, i++)
{
*buf = (NFDATA & 0xFF);
buf++;
}
}
NAND_CHIP_DISABLE; //取消片选信号
return 0;
}
修改board/samsung/smdk2440/ makefile
COBJS := smdk2440.o flash.o nand_read.o
drivers/mtd/nand/s3c2440_nand.c 目录下新建s3c2440_nand.c文件实现对nand FLASH的操作。
#include <common.h>
#if 0
#define DEBUGN printf
#else
#define DEBUGN(x, args ...) {}
#endif
#include <nand.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <asm/io.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000 //Nand配置寄存器基地址
#define NFCONF __REGi(NF_BASE + 0x0) //偏移后还是得到配置寄存器基地址
#define NFCONT __REGi(NF_BASE + 0x4) //偏移后得到Nand控制寄存器基地址
#define NFCMD __REGb(NF_BASE + 0x8) //偏移后得到Nand指令寄存器基地址
#define NFADDR __REGb(NF_BASE + 0xc) //偏移后得到Nand地址寄存器基地址
#define NFDATA __REGb(NF_BASE + 0x10) //偏移后得到Nand数据寄存器基地址
#define NFMECCD0 __REGi(NF_BASE + 0x14) //偏移后得到Nand主数据区域ECC0寄存器基地址
#define NFMECCD1 __REGi(NF_BASE + 0x18) //偏移后得到Nand主数据区域ECC1寄存器基地址
#define NFSECCD __REGi(NF_BASE + 0x1C) //偏移后得到Nand空闲区域ECC寄存器基地址
#define NFSTAT __REGb(NF_BASE + 0x20) //偏移后得到Nand状态寄存器基地址
#define NFSTAT0 __REGi(NF_BASE + 0x24) //偏移后得到Nand ECC0状态寄存器基地址
#define NFSTAT1 __REGi(NF_BASE + 0x28) //偏移后得到Nand ECC1状态寄存器基地址
#define NFMECC0 __REGi(NF_BASE + 0x2C) //偏移后得到Nand主数据区域ECC0状态寄存器基地址
#define NFMECC1 __REGi(NF_BASE + 0x30) //偏移后得到Nand主数据区域ECC1状态寄存器基地址
#define NFSECC __REGi(NF_BASE + 0x34) //偏移后得到Nand空闲区域ECC状态寄存器基地址
#define NFSBLK __REGi(NF_BASE + 0x38) //偏移后得到Nand块开始地址
#define NFEBLK __REGi(NF_BASE + 0x3c) //偏移后得到Nand块结束地址
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
ulong IO_ADDR_W = NF_BASE;
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02x/n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE)) //要写的是地址
IO_ADDR_W |= S3C2440_ADDR_NALE;
if (!(ctrl & NAND_ALE)) //要写的是命令
IO_ADDR_W |= S3C2440_ADDR_NCLE;
if (ctrl & NAND_NCE)
NFCONT &= ~S3C2440_NFCONT_nCE; //使能nand flash
else
NFCONT |= S3C2440_NFCONT_nCE; //禁止nand flash
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
}
static int s3c2440_dev_ready(struct mtd_info *mtd)
{
DEBUGN("dev_ready/n");
return (NFSTAT & 0x01);
}
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power();
DEBUGN("board_nand_init()/n");
/*clk_power->CLKCON |= (1 << 4);*/
writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2440_hwcontrol;
nand->dev_ready = s3c2440_dev_ready;
return 0;
}
然后,在drivers/mtd/nand/Makefile文件中添加s3c2440_nand.c的编译项,如下:
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
在u-boot-2010.12/include/configs/smdk2440.h中增加宏定义:
# define CONFIG_NAND_S3C2440
重新编译,将u-boot.bin下载到内存运行,可以运行,FLASH也正常的读写。注意,此时我们的uboot还不支持从NAND FLASH启动,前面的步骤只是为了调试方便,我们将可以看到在内存中运行的u-boot成功的将NAND FLASH中的数据拷贝到了内存中CONFIG_SYS_LOAD_ADDR的位置。接下来我们让其支持在NAND FLASH中的启动。
将上面的ldr r0, =CONFIG_SYS_LOAD_ADDR和ldr r1, =CONFIG_SYS_LOAD_ADDR替换为ldr r0, =CONFIG_SYS_TEXT_BASE和ldr r1, =CONFIG_SYS_TEXT_BASE。
通过查看u-boot.map可以看到,我们的nand_read_ll()函数被连接在4K之后的位置,所以根本无法再启动时实现数据到内存的拷贝。因此我们根据网友的说法修改arch/arm/cpu/arm920t/u-boot.lds如下:
.text :
{
arch/arm/cpu/arm920t/start.o (.text)
board/samsung/smdk2440/lowlevel_init.o (.text)
board/samsung/smdk2440/nand_read.o (.text)
*(.text)
}
编译发现,编译通不过,出现重定义的错误。这可能是新版本的编译和连接规则有变化导致的,具体原因还不清楚,因此我们采用其他的办法。
board/samsung/smdk2440/libsmdk2440.o: In function `nand_read_ll':
/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/nand_read.c:30: multiple definition of `nand_read_ll'
board/samsung/smdk2440/nand_read.o:/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/nand_read.c:30: first defined here
board/samsung/smdk2440/libsmdk2440.o: In function `lowlevel_init':
/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/lowlevel_init.S:137: multiple definition of `lowlevel_init'
board/samsung/smdk2440/lowlevel_init.o:/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/lowlevel_init.S:137: first defined here
make: *** [u-boot] 错误 1
这可能是新版本的编译和连接规则有变化导致的,具体原因还不清楚,因此我们采用其他的办法。修改arch/arm/cpu/arm920t/u-boot.lds如下:
.text :
{
arch/arm/cpu/arm920t/start.o (.text)
board/samsung/smdk2440/ libsmdk2440.o (.text)
arch/arm/lib/libarm.o (.text)
*(.text)
}
编译之后发现,board_init_f函数还是超过了4K,我们只能对前面的代码进行瘦身了,我们的目标板没有NOR FLASH,所以我们取消NOR FLASH的支持。
在u-boot-2010.12/include/configs/smdk2440.h中增加宏定义:
/*去掉NOR FLASH支持*/
#define CONFIG_SYS_NO_FLASH
#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
#define CONFIG_CMD_IMLS /* List all found images */
修改board/samsung/smdk2440/ makefile,取消对flash的编译。
COBJS := smdk2440.o nand_read.o
编译后下载到内存,杯具又发生了,跑进board_init_r()函数的时候死机了。至此相当的郁闷了,没办法再修改arch/arm/cpu/arm920t/u-boot.lds如下:
.text :
{
arch/arm/cpu/arm920t/start.o (.text)
board/samsung/smdk2440/ libsmdk2440.o (.text)
*(.text)
}
在编译,下载到内存运行,可以运行。但是还是相当杯具的,通过查看u-boot.map可以看到arch/arm/lib/libarm.o被连接到了4K之外,4K之内没有这个程序我们是不可能实现NAND启动的。但是天无绝人之路,我们可以让U-boot提前进入内存运行。思路是,我们提前将代码拷贝到内存中,提前跳转到内存中运行不再回来。修改arch/arm/cpu/arm920t/start.S文件如下:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
//下面添加2440中u-boot从Nand Flash启动
#ifdef CONFIG_S3C2440_NAND_BOOT
mov r1, #NAND_CTL_BASE //复位Nand Flash
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF] //设置配置寄存器的初始值,参考s3c2440手册
ldr r2, [r1, #oNFCONF]
ldr r2, =( (1<<4)|(0<<1)|(1<<0) )
str r2, [r1, #oNFCONT] //设置控制寄存器
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) //RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff //复位command
strb r2, [r1, #oNFCMD]
mov r3, #0 //等待
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] //等待就绪
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 //取消片选
str r2, [r1, #oNFCONT]
//get read to call C functions (for nand_read())
ldr sp, DW_STACK_START //为C代码准备堆栈,DW_STACK_START定义在下面
mov fp, #0
//copy U-Boot to RAM
ldr r0, =CONFIG_SYS_TEXT_BASE//传递给C代码的第一个参数:u-boot在RAM中的起始地址
mov r1, #0x0 //传递给C代码的第二个参数:Nand Flash的起始地址
mov r2, #UBOOT_LENGTH //传递给C代码的第三个参数:u-boot的长度大小
bl nand_read_ll //此处调用C代码中读Nand的函数,现在还没有要自己编写实现
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2: b loop2 //infinite loop
ok_nand_read:
//检查搬移后的数据,如果前4k完全相同,表示搬移成功
mov r0, #0
ldr r1, =CONFIG_SYS_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 relocations /*注意此句,直接跳转到relocate_code 函数的调整部分,因为我们不打算在board_init_f()函数中再回来了*/
bne go_next
notmatch:
loop3: b loop3 //infinite loop
#endif //CONFIG_S3C2440_NAND_BOOT
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r2, _TEXT_BASE
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r1!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
relocations: /*增加标号,以便跳转到这里*/
ldr r6, =CONFIG_SYS_TEXT_BASE /*注意,R6下面被用到表示新的目标地址*/
#ifndef CONFIG_PRELOADER
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text base */
sub r9, r6, r0 /* r9 <- relocation offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
add r10, r10, r0 /* r10 <- sym table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4] /* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
clear_bss:
#ifndef CONFIG_PRELOADER
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
ldr r3, _TEXT_BASE /* Text base */
mov r4, r6 /* reloc addr */
add r0, r0, r3 /*注意此句修改*/
add r1, r1, r3 /*注意此句修改*/
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
/*
bl coloured_LED_init
bl red_LED_on
*//* by bsc 2011/2/23 13:44:29*/
#endif
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r0,=0x00000000
/*bl board_init_f*/ /*删除此句,我们用绝对地址跳转到内存去了,不再回来了*/
ldr pc, _board_init_f /*增加此句,我们用绝对地址跳转到内存去了,不再回来了*/
_board_init_f: /*增加此句,我们用绝对地址跳转到内存去了,不再回来了*/
.word board_init_f
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#ifdef CONFIG_NAND_SPL
ldr r0, _nand_boot_ofs
mov pc, r0
_nand_boot_ofs:
.word nand_boot
#else
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr
_board_init_r_ofs:
.word board_init_r - _start
#endif
_rel_dyn_start_ofs:
.word __rel_dyn_start - _start
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start
_dynsym_start_ofs:
.word __dynsym_start - _start
.align 2 /*add by bsc 2010-2-6 13:11*/
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
修改完arch/arm/cpu/arm920t/start.S文件之后,我们会发现,有一句非常重要的代码被我们删除再也执行不到了,那就是设置堆栈指针:mov sp, r4
因此我们需要在board_init_f()函数中设置。
修改/arch/arm/lib/board.c代码如下:
首先将board_init_f()与board_init_r()函数的顺序调换下,因为我们要在board_init_f()中调用board_init_r()。
gd->mon_len = 0x700000 ; /*修改此句以保证与配置的一致性add by bsc 具体原因请查看代码中对此变量的使用即可明白,注意我们的 _TEXT_BASE=0x33f80000*/
函数最后:
__asm__ __volatile__("mov sp,%0"::"r"(addr_sp):"sp");/*add by bsc 2011/2/24 15:17:48*/
#ifdef CONFIG_S3C2440_NAND_BOOT /*add by bsc 2011/2/24 15:18:04*/
board_init_r(id, addr);
#else
relocate_code (addr_sp, id, addr);
/* NOTREACHED - relocate_code() does not return */
#endif
/*relocate_code (addr_sp, id, addr);*//*add by bsc 2011/2/24 15:18:28*/
/* NOTREACHED - relocate_code() does not return */
然后修改board/samsung/smdk2440/config.mk如下:
CONFIG_SYS_TEXT_BASE = 0x33f80000
然后修改include/configs/smdk2440.h如下:
增加宏定义:
#define UBOOT_LENGTH 0x40000 /*uboot大小256K*/
删除宏定义:
#define CONFIG_SKIP_LOWLEVEL_INIT /*在内存中调试时增加此宏定义 by bsc */
然后编译,烧写到NAND FLASH中,重启之后你会发现,终于可以运行啦。
测试中发现,go命令好像有问题,直接死机了,其他一切正常。
如果你还想看到u-boot启动时的输出版本信息等,修改/arch/arm/lib/board.c代码如下:board_init_r函数中修改
board_init(); /* Setup chipselects */
#ifdef CONFIG_SERIAL_MULTI
serial_initialize();
#endif
debug ("Now running in RAM - U-Boot at: %08lx/n", dest_addr);
display_banner();
display_dram_config();
#ifdef CONFIG_LOGBUFFER
logbuff_init_ptrs ();
#endif
好了,现在uboot已经可以支持NAND FLASH启动和读写了。
我们还可以在common/env_common.c文件中的default_environment[]数组中增加
#if 1 /*add by bsc */
"uu=" "t 0x30000000 u-boot.bin;nand erase 0x0 0x30000;nand write 0x30000000 0x0 0x30000" "/0"
"kkn=" "t 0x30008000 zImage_nfs;bootm" "/0"
"kk=" "t 0x30000000 zImage;nand erase 0x50000 0x300000;nand write 0x30000000 0x50000 0x200000" "/0"
"yy=" "t 0x30000000 rootyaffs2.img;nand erase 0x250000 0x3db0000;nand write.yaffs2 0x30000000 0x250000 $(filesize)" "/0"
"firstboot=" "set bootcmd $(normalboot);save;nand erase 0x50000 0x3f00000;run kk;run yy" "/0"
"normalboot=" "nand read 0x30008000 0x50000 0x200000;bootm 0x30008000" "/0"
#endif
以使用 run uu;run yy这样的命令来实现一些操作。