目标板:FL2440
硬件资源:64M SDRAM/256M nandflash(k9f2g08u0a)/4M nor flash(JS28F320)
开发环境:fedora 14
源码:u-boot-2009.11
交叉编译工具链:cross-3.3.2.tar.bz2
天嵌TQ2440 uboot-1.16源码(主要参考256M nand flash 代码重定位部分程序)
关于uboot的源码结构这里就不多说了,网上很这方面的资料。注意,此文章不支持nor flash启动。
一、建立开发板项目,并尝试编译
1、下面的操作都是基于目录[root@fzliu u-boot-2009.11]#
2、指定交叉编译器
[root@fzliu u-boot-2009.11]# vim Makefile,
修改163行为CROSS_COMPILE ?=arm-linux-
3、在board/samsung/下建立自己的开发板项目
[root@fzliu u-boot-2009.11]# mkdir board/samsung/rocko2440
(取名rocko是因为喜欢Sylvester Stallone主演的励志电影《洛奇》,)
4、注意,uboot的移植是基于源码包的smdk2410开发板,因为2410和2440资源并不多。将smdk2410下所有文件复制到rocko2440.
[root@fzliu u-boot-2009.11]# cp -rf board/samsung/smdk2410/* board/samsung/rocko2440/
[root@fzliu u-boot-2009.11]# mv board/samsung/smdk2410/smdk2410.c board/samsung/rocko2440/rocko2440.c
[root@fzliu u-boot-2009.11]# cp include/configs/smdk2410.h include/configs/rocko2440.h( 建立2440头文件)
[root@fzliu u-boot-2009.11]# vim board/samsung/rocko2440/Makefile
28行改为:
COBJS := rocko2440.o flash.o //因在 rocko2440 下我们将 smdk2410.c 改名为rocko2440.c
5、参考smdk2410_config建立rocko2440_configs选项
[root@fzliu u-boot-2009.11]# vim Makefile
在3050行添加:
rocko2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t rocko2440 samsung s3c24x0
*说明:arm :CPU 的架构(ARCH)
arm920t:CPU 的类型
rocko2440:对应在 board 目录下建立新的开发板项目的目录
samsung:新开发板项目目录的上级目录,如直接在 board 下建立新的开发板项
目的目录,则这里就为 NULL
s3c24x0:CPU 型号
*注意:编译选项格式的第二行要用 Tab 键开始,否则编译会出错
6、测试编译新建的 rocko2440 开发板项目
[root@fzliu u-boot-2009.11]# make rocko2440_config
Configuring for rocko2440 board...(此信息表明设置正确)
7、尝试编译
[root@fzliu u-boot-2009.11]# make
此时有可能会出现编译错误,
linux/3.3.2/libgcc.a(_modsi3.oS) uses hardware FP, whereas u-boot uses software FP
解决方法:
[root@fzliu u-boot-2009.11]# vim cpu/arm920t/config.mk
24行改为:
PLATFORM_RELFLAGS += -fno-common -ffixed-r8
#-msoft-float
[root@fzliu u-boot-2009.11]# make
编译后在目录下生成u-boot.bin文件,移植的第一步完成。别急哦,真正的工作还没开始呢
二、分析uboot启动流程之stage1,并修改源码使之能在FL2440开发板上运行。
一般在嵌入式系统软件开发中,在所有源码文件编译完成之后,链接器要读取一个链接分配文件,在该文件中定义了程序的入口点,代码段、数据段等分配情况等。对于rocko2440开发板来说,这个链接文件就是: cpu/arm920t/u-boot.lds,从该文件知程序入口点为_start(在cpu/arm920t/start.S文件中)
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)//指定程序入口点为_start
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
_end = .;
}
1、知道了程序的入口点是_start,那么我们就从这个文件入手,一步步剖析uboot stage1之启动流程
[root@fzliu u-boot-2009.11]# cpu/arm920t/start.S
这里只分析start.S的启动流程
(1)首先,跳转到start_code执行,设置cpu工作模式为SVC模式,关闭看门狗,屏蔽中断,设置时钟分频比
(2)b1 cpu_init_crit
这部分代码将进行清flush 清caches,关闭MMU功能,调用lowlevel_init函数配置SDRAM(在 board/samsung/rocko2440/目录下),下面修改SDRAM的刷新频率:
[root@fzliu u-boot-2009.11]#vim board/samsung/rocko2440/lowlevel_init.c
将REFCNT改为:
#define REFCNT 0x4f4 (refresh_count)
S3C2440手册知,计算公式:Refresh period = (2^11-refresh_count+1)/HCLK
SDRAM手册知:Refresh period =8192/64ms
下面start.S设置FCLK为405MHZ,分频系数 FCLK:HCLK:PCLK = 1:4:8 ,HCLK=100MHZ
(3)设置堆栈,因为下面的代码重定位程序将使用C函数。注意一定要在调用C前设置堆栈。
(4)代码重定位,这里会有两种情况。如果系统是从norflash启动或者直接下到SDRAM中运行,则不需要进行代码搬移,直接跳到清bss段代码,最后进入uboot的stage2阶段入口_start_armboot;如果从nandflash启动,则调用C函数进行代码搬移,然后跳到清bss段代码,最后进入uboot的stage2阶段入口_start_armboot。
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#if defined(CONFIG_S3C2440) //区别与其他开发板
#define GPBCON 0x56000010 //fl2440开发板的GPB5 6 8 10 控制四个LED灯
#define GPBDAT 0x56000014
#define GPBUP 0x56000018
ldr r0,=GPBUP
ldr r1,=0x00
str r1,[r0]
ldr r0,=GPBCON
ldr r1,=0xddd7fc
str r1,[r0]
ldr r0,=GPBDAT
ldr r1,=0xffc0 //GPB5亮,其它灭
str r1,[r0]
#endif
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*
* 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)|| defined(CONFIG_S3C2440)
/* 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 //下面 2410 和 2440 的寄存器地址是一致的
# 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
# if defined(CONFIG_S3C2440)//添加 s3c2440 的中断禁止部分
ldr r1, =0x7fff //根据 2440 芯片手册,INTSUBMSK 寄存器有 15位可用
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
# if defined(CONFIG_S3C2440) //添加 s3c2440 的时钟部分
#define MPLLCON 0x4C000004 //系统主频配置寄存器基地址
#define UPLLCON 0x4C000008 //USB 时钟频率配置寄存器基地址
ldr r0, =CLKDIVN //设置分频系数 FCLK:HCLK:PCLK = 1:4:8
mov r1, #5
str r1, [r0]
ldr r0, =MPLLCON //设置系统主频为 405MHz
ldr r1, =0x7F021 //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分
str r1, [r0]
ldr r0, =UPLLCON //设置 USB 时钟频率为 48MHz
ldr r1, =0x38022 //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分
str r1, [r0]
# else //其他开发板的时钟部分,这里就不用管了,我们现在是做 2440 的
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */ /*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif /* Set up the stack */stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
sub r0, r0, #CONFIG_SYS_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 */ #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 clear_bss
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
#if 1
bl CopyCode2Ram //此处调用 C 代码中读 Nand 的函数,现在还没有要自己编写实现
#else
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
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 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
/*进入stage2 入口函数_start_armboot*/
ldr pc, _start_armboot
_start_armboot: .word start_armboot/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INITcpu_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
bl lowlevel_init
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
2、完成了start.S修改后,在include/configs/rocko2440.h下添加CONFIG_S3C2440 配置选项,
[root@fzliu u-boot-2009.11]# vim include/configs/rocko2440.h
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
3、S3C2440 的时钟部分除了在 start.S 中添加外,还要分别在 board/samsung/rocko2440/rocko2440.c 和
cpu/arm920t/s3c24x0/speed.c 中修改或添加部分代码,如下:
[root@fzliu u-boot-2009.11]# vim board/samsung/rocko2440/rocko2440.c
黑体部分有效
#define FCLK_SPEED 2
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
#elif FCLK_SPEED==2 /* Fout = 405MHz */
#define M_MDIV 0x7F //这三个值根据 S3C2440 芯片手册“PLL VALUE SELECTION TABLE”部分进行设置
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
#define USB_CLOCK 2 #if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#elif USB_CLOCK==2 /* Fout = 48MHz */
#define U_M_MDIV 0x38 //这三个值根据 S3C2440 芯片手册“PLL VALUESELECTIONTABLE”部分进行设置
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
[root@fzliu u-boot-2009.11]# vim cpu/arm920t/s3c24x0/speed.c
static ulong get_PLLCLK(int pllreg)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
ulong r, m, p, s;
if (pllreg == MPLL)
r = readl(&clk_power->MPLLCON);
else if (pllreg == UPLL)
r = readl(&clk_power->UPLLCON);
else
hang();
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
#if defined(CONFIG_S3C2440)
if(pllreg == MPLL)
{ //参考S3C2440 芯片手册上的公式:PLL=(2 * m * Fin)/(p * 2 s )
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
}
#endif
return (CONFIG_SYS_CLK_FREQ * m) / (p << s);
}
/* return FCLK frequency */
ulong get_FCLK(void)
{
return get_PLLCLK(MPLL);
}
/* return HCLK frequency */
ulong get_HCLK(void)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
#if defined(CONFIG_S3C2440)
return(get_FCLK()/4);
#endif
return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK();
}
/* return PCLK frequency */
ulong get_PCLK(void)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
return (readl(&clk_power->CLKDIVN) & 1) ? get_HCLK() / 2 : get_HCLK();
}
/* return UCLK frequency */
ulong get_UCLK(void)
{
return get_PLLCLK(UPLL);
}
#endif
4、到此,uboot是否就支持了nandflash 启动了呢,还记得我们在start.S文件中添加的用于将uboot从nandflash搬到SDRAM中的函数CopyCode2Ram 吗?现在我们就去实现这个函数,在board/samsung/rocko2440/下新建一个nand_read.c
[root@fzliu u-boot-2009.11]# vim board/samsung/rocko2440/nand_read.c(这部分参考TQ2440 uboot1.1.6)
#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_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
#define NAND_SECTOR_SIZE_LP 2048
#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1)
#define BUSY 1
#if defined(CONFIG_S3C2440)
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
#define GPBUP (*(volatile unsigned long *)0x56000018)
#endif
/* low level nand read function */
ldr r0, =TEXT_BASE//传递给 C 代码的第一个参数:u-boot 在 RAM 中的起始地址
mov r1, #0x0 //传递给 C 代码的第二个参数:Nand Flash 的起始地址
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 //r2 <- size of armboot 传递给 C 代码的第三个参数:u-boot 的长度大小(128k)
static void s3c2440_wait_idle(void)
{
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
static void s3c2440_nand_select_chip(void)
{
int i;
NFCONT &= ~(1<<1);
for(i=0; i<10; i++);
}
static void s3c2440_nand_deselect_chip(void)
{
NFCONT |= (1<<1);
}
static void s3c2440_write_cmd(int cmd)
{
NFCMD = cmd;
}
static void s3c2440_nand_reset(void)
{
s3c2440_nand_select_chip();
s3c2440_write_cmd(0xff); //reset
s3c2440_wait_idle();
s3c2440_nand_deselect_chip();//disable chip select
}
static void s3c2440_write_addr_lp(unsigned int addr)
{
int i;
int col, page;
col = addr & NAND_BLOCK_MASK_LP;//取NAND_BLOCK_MASK_LP的整数倍得到col
page = addr / NAND_SECTOR_SIZE_LP;//取NAND_BLOCK_MASK_LP的余数得到row
NFADDR = col & 0xff; /* Column Address A0~A7 */
for(i=0; i<10; i++);
NFADDR = (col >> 8) & 0x0f; /* Column Address A8~A11 */
for(i=0; i<10; i++);
NFADDR = page & 0xff; /* Row Address A12~A19 */
for(i=0; i<10; i++);
NFADDR = (page >> 8) & 0xff; /* Row Address A20~A27 */
for(i=0; i<10; i++);
//if (b128MB == 0)
NFADDR = (page >> 16) & 0x03; /* Row Address A28~A29 or 0x01? */
for(i=0; i<10; i++);
}
static unsigned char s3c2440_read_data(void)
{
return NFDATA;
}
int nand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
char dat;
if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP))
{
return -1;
}
s3c2440_nand_select_chip();
for(i=start_addr; i < (start_addr + size);)
{
/* Check Bad Block */
if(0){
int col, page;
col = i & NAND_BLOCK_MASK_LP;
page = i / NAND_SECTOR_SIZE_LP;
s3c2440_write_cmd(0x00);
NFADDR = 5;
for(j=0; j<10; j++);
NFADDR = 8;
for(j=0; j<10; j++);
NFADDR = page & 0xff; /* Row Address A12~A19 */
for(j=0; j<10; j++);
NFADDR = (page >> 8) & 0xff; /* Row Address A20~A27 */
for(j=0; j<10; j++);
//if (b128MB == 0)//big page
NFADDR = (page >> 16) & 0x03; /* Row Address A28~A29 */
for(j=0; j<10; j++);
s3c2440_write_cmd(0x30);
s3c2440_wait_idle();
dat = s3c2440_read_data();
/*slect chip */
s3c2440_nand_deselect_chip();
if(dat != 0xff)
i += 131072; // 1 Block = 2048*64= 131072
/* Read Page */
/* slect chip */
s3c2440_nand_select_chip();
}///*end of Check Bad Block */
/* send read0 cmd */
s3c2440_write_cmd(0);
/* Write Address */
s3c2440_write_addr_lp(i);
s3c2440_write_cmd(0x30);
s3c2440_wait_idle();
//NAND_SECTOR_SIZE_LP=2048bytes
for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++)
{
*buf = s3c2440_read_data();
buf++;
}
}
/* disable chip select */
s3c2440_nand_deselect_chip();
return 0;
}
/* nor boot return 1*/
int bBootFrmNORFlash(void)
{
volatile unsigned int *pdw = (volatile unsigned int *)0;
unsigned int dwVal;
dwVal = *pdw;
*pdw = 0x12345678;
if (*pdw != 0x12345678)
{
return 1;
}
else
{
*pdw = dwVal;
return 0;
}
}
void nand_init_ll(void)
{
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
NFCONT = (1<<4)|(1<<1)|(1<<0);
s3c2440_nand_reset();
}
int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
{
unsigned int *pdwDest;
unsigned int *pdwSrc;
int i;
if (bBootFrmNORFlash())
{
pdwDest = (unsigned int *)buf;
pdwSrc = (unsigned int *)start_addr;
/* boot form NOR Flash*/
for (i = 0; i < size / 4; i++)
{
pdwDest[i] = pdwSrc[i];
}
return 0;
}
else
{
/* init NAND Flash */
nand_init_ll();
nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));
}
return 0;
}
5、修改链接文件,,在 cpu/arm920t/u-boot.lds 中,这个 u-boot 启动连接脚本文件决定了 u-boot 运行的入口地址,以及各个段的存储位置,这也是链接定位的作用。添加下面两行代码的主要目的是防止编译器把我们自己添加的用于 nandboot 的子函数放到 4K 之后,否则是无法启动的。如下:
.text :
{
cpu/arm920t/start.o (.text)
board/samsung/rocko2440/lowlevel_init.o (.text)
board/samsung/rocko2440/nand_read.o (.text)
*(.text)
6、到此完成了对从nandflash启动的支持,下面修改uboot启动时命令行前的名字。
[root@fzliu u-boot-2009.11]# vim include/configs/rocko2440.h //修改命令行前的名字
#define CONFIG_SYS_PROMPT "[rocko2440]#" //将命令行前的名字改成[rocko2440]
7、[root@fzliu u-boot-2009.11]# make 将生成的u-boot.bin 下载到nandflash中,从nandflash启动,将会看到如下信息:
U-Boot 2009.11 (Oct 24 2011 - 18:12:47)
DRAM: 64 MB
## Unknown FLASH on Bank 0: ID 0xffff, Size = 0x00000000 = 0 MB
Flash: 0 kB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
[rocko2440]#
8、现在的 Nand 还不能做任何事情,而且也没有显示有关 Nand 的任何信息,所以只能说明上面的这些步骤只是完成了 Nand 移植的 Stage1 部分。关于stage2的nandflash驱动移植将在后面补上。