Nand Flash 中的复制可能存在一些差别,但是基本思想仍然相同实现代码的搬迁。
Nand Flash 相比Nor Flash各自有自己的优势,同时也有自己的劣势,S3C2440支持两种Flash的引导
方式。其中S3C2440提供了NADN FLASH的控制器,但是该控制器于S3C2410的存在较大的差别,
因此需要重写代码,同时TQ2440的Nand Flash是K9F2G08UXA ,是一个256M的Flash。由于uboot
属于最底层的程序,所以需要对芯片资料有所认识,最好熟悉芯片基本的操作和特性。
K9F2G08UXA 是一个具有128K页,2048块,每一块64页,每一页具有(2K+64)byte,2K是主区,
64是信息区域,每一块是(128K+4K)byte的空间。所有的操作都是通过一个8位的IO实现。对每
一页的访问通过列地址进行访问,2K空间一共需要11个位宽,因此列访问需要两次,第一次前8位,
第二次前4位,后4位为0。行地址和列地址是分开访问的。页访问通过行地址实现,一共128K,则
需要17位位宽,这样8位IO口需要三次才能访问完全,前两次的8位,后一次的1位,其他位都必
须为0。因此K9F2G08UXA 的地址是5次地址方式。这才导致了5个周期输入。实质上存储空间不
止256M。具体的操作的方式是通过一些命令实现的,因此需要熟悉命令,才能实现控制。
U-boot中Nand Flash的实现主要是u-boot将自身从nand Flash中搬移到内存中去,然后才能执行,这
个过程需要我们采用汇编代码实现。
/*建议在修改下一项的过程中最好在修改前编译一次,确保没有错误再修改这样才能知道是那一阶段
出了问题,便于修改*/
具体的操作如下:
1、添加Nand Flash操作的寄存器
2、屏蔽从Nor Flash复制的代码
/*屏蔽掉从Nor Flash启动的方式*/
#if 0
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
....
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
3、添加从Nand Flash引导的代码
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
/*添加从Nand Flash 引导的代码*/
#ifdef CONFIG_S3C2440_NAND_BOOT /*增加条件编译*/
mov r1,#NAND_CTL_BASE
/*两种参数均可以*/
/* ldr r2,=(0<<12)|(3<<8)|(0<<4)|(3<<2)|(1<<1)*/
ldr r2,=( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
/*设置寄存器NFCONF,具体的值查看手册*/
str r2,[r1,#oNFCONF]
/*将NFCONF的值加载到r2*/
ldr r2,[r1,#oNFCONF]
/*两种参数均可以*/
/* ldr r2,=(1<<4)|(1<<1)|(1<<0)*/
ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
/*设置寄存器NFCONT*/
str r2,[r1,#oNFCONT]
ldr r2,[r1,#oNFCONT]
/*如果采用上面注释起来的代码,下面的三句代码也需要注释起来*/
ldr r2,=(0x06) //清除RnB
str r2,[r1,#oNFSTAT]
//加载寄存器中的内容
ldr r2,[r1,#oNFSTAT]
mov r2,#0xff /*复位的命令*/
/*存储一个字节到r1+oNFCMD*/
strb r2,[r1,#oNFCMD]
mov r3,#0 /*等待*/
nand1:/*实际上就是一个循环,相当于等待操作*/
add r3,r3,#0x1
cmp r2,#0xa
blt nand1
nand2:
ldr r2,[r1,#oNFSTAT] /*读Nand Flash的控制器的状态寄存器*/
tst r2,#0x4 /*检查是否准备完毕*/
beq nand2
ldr r2,[r1,#oNFCONT]
/*参看手册*/
orr r2,r2,#0x02 /*取消片选*/
str r2,[r1,#oNFCONT]
/*为C代码准备堆栈空间*/
ldr sp,DW_STACK_START
mov fp,#0
/*复制代码到SDRAM中*/
ldr r0,=TEXT_BASE /*复制到ARM中的真实地址*/
mov r1,#0x0 /*代码在Nand Flash的起始地址*/
mov r2,#0x30000 /*u-boot的长度*/
bl nand_read_ll /*调用C代码读Nand Flash*/
tst r0,#0x0 /*根据返回值是否是0,如果是0,则正确操作*/
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 /*无穷的循环,出错误*/
/*在Nand Flash模式下,S3C2440内部的4KRAM被映射到0x0地址处,上电以后CPU自动复制
Nand Flash的4K代码到该地址
处*/
/*比较搬移到TEXT_BASE地址处的数据和内部存储器RAM的前4K数据,如果完全相同,则
表示搬移成功*/
ok_nand_read:
mov r0,#0 /*访问地址内部的RAM:0x00000000*/
ldr r1,=TEXT_BASE /*访问地址SDRAM:TEXT_BASE处的数据*/
mov r2,#0x400 /*CPU自动搬移的4K代码用来比较,4k = 1024 * 4 byte*/
go_next:
ldr r3,[r0],#4 /*将r0的内容复制r3,然后r0指向的地址变为原来的r0 = r0 +4*/
ldr r4,[r1],#4 /*将r1的内容复制给r4,然后改变r1指向的地址r1 = r1 +4,因为每一次加载
都是4个字节*/
teq r3,r4
bne notmatch /*如果内容步相符,则指出不符合*/
/*如果数据符合,则将r2自减,当等于0时说明比较操作完成,每次减去4,是因为每次操作的数
据都是4字节*/
subs r2,r2,#4
beq stack_setup /*说明4K代码比较完成*/
bne go_next /*说明还没有比较完成*/
notmatch:
loop3:
b loop3 /*无限循环,出错*/
#endif /*CONFIG_S3C2440_NAND_BOOT*/
定义DW_STACK_START
_start_armboot: .word start_armboot
/*添加对DW_STACK_START的定义*/
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
开启之前关闭的cpu_init_crit
#if 1
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
#endif
在板子相关的文件夹中添加nand_read_ll的操作函数nand_read.c
[root@Gong-Computer u-boot-2010.06]# gedit board/samsung/smdk2440/nand_read.c
#include <config.h>
#define BUSY 1
#define NF_BASE 0x4E000000
#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 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 |= BUSY)
#define NAND_DETECT_RB { while(!(NFSTAT & BUSY));}
#define NAND_SECTOR_SIZE 2048
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
/*TQ2440 NAND FLASH的5周期地址写方式 */
static void s3c2440_write_addr_lp(unsigned int addr)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&NFADDR;
int col, page;
col = addr & NAND_BLOCK_MASK;
page = addr / NAND_SECTOR_SIZE;
*p = col & 0xff; /* Column Address A0~A7 */
for(i=0; i<10; i++);
*p = (col >> 8) & 0x0f; /* Column Address A8~A11 */
for(i=0; i<10; i++);
*p = page & 0xff; /* Row Address A12~A19 */
for(i=0; i<10; i++);
*p = (page >> 8) & 0xff; /* Row Address A20~A27 */
for(i=0; i<10; i++);
*p = (page >> 16) & 0x01; /* Row Address A28~A29 */
for(i=0; i<10; i++);
}
/* 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; //查看手册可知
s3c2440_write_addr_lp(i);
/*2k page*/
NFCMD = 0x30; //查看手册可知
NAND_DETECT_RB;
for(j=0; j < NAND_SECTOR_SIZE; j++, i++)
{
*buf = NFDATA;
buf++;
}
}
NAND_CHIP_DISABLE; /*取消片选信号*/
return 0;
}
将刚加入的函数添加到板级相关的Makefile中,这样就能是它得到编译
[root@Gong-Computer u-boot-2010.06]# vi board/samsung/smdk2440/Makefile
COBJS := smdk2440.o flash.o nand_read.o
SOBJS := lowlevel_init.o
还有一个比较重要的修改就是我们必须取保cpu_init_crit在NAND_FLASH相关的操作之前进行,因
此需要确保lowlevel_init.o 的内容在nand_read.o之前,因此需要修改链接文本文件u-boot.lds,将
lowlevel_init.o 直接写在nand_read.o前面。
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/cpu/arm920t/u-boot.lds
. = ALIGN(4);
.text :
{
arch/arm/cpu/arm920t/start.o (.text)
board/samsung/smdk2440/lowlevel_init.o (.text)
board/samsung/smdk2440/nand_read.o (.text)
*(.text)
}
然后编译调试下载:
[root@Gong-Computer u-boot-2010.06]# make -d
本来打算 调试,但是发现在nor flash模式下不能调试,每次都直接死机,所以下载到nand flash中
调试模式的编译结果:
......
Must remake target `System.map'.
Invoking recipe from Makefile:426 to update target `System.map'.
Putting child 0x9817dc0 (System.map) PID 27892 on the chain.
Live child 0x9817dc0 (System.map) PID 27892
Reaping winning child 0x9817dc0 PID 27892
Removing child 0x9817dc0 PID 27892 from chain.
Successfully remade target file `System.map'.
Finished prerequisites of target file `all'.
Must remake target `all'.
利用天嵌的u-boot下载。然后切换到NADN_FLASH模式下得到下面的结果:
##### Boot for Nor Flash Main Menu #####
##### EmbedSky TFTP download mode #####
[1] Download u-boot.bin to Nand Flash
[2] Download Eboot (eboot.nb0) to Nand Flash
[3] Download Linux Kernel (zImage.bin) to Nand Flash
[4] Download stepldr.nb1 to Nand Flash
[5] Set TFTP parameters(PC IP,TQ2440 IP,Mask IP...)
[6] Download YAFFS image (root.bin) to Nand Flash
[7] Download Program (uCOS-II or TQ2440_Test) to SDRAM and Run it
[8] Boot the system
[9] Format the Nand Flash
[0] Set the boot parameters
[a] Download User Program (eg: uCOS-II or TQ2440_Test)
[b] Download LOGO Picture (.bin) to Nand Flash
[l] Set LCD Parameters
[o] Download u-boot to Nor Flash
[p] Test network (TQ2440 Ping PC's IP)
[r] Reboot u-boot
[t] Test Linux Image (zImage)
[q] Return main Menu
Enter your selection: 1
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.10.154; our IP address is 192.168.10.122
Filename 'u-boot.bin'.
Load address: 0x30000000
Loading: T #######
done
Bytes transferred = 101628 (18cfc hex)
NAND erase: device 0 offset 0x0, size 0x40000
Erasing at 0x20000 -- 100% complete.
OK
NAND write: device 0 offset 0x0, size 0x18cfc
Writing data at 0x18800 -- 100% complete.
101628 bytes written: OK
切换到NAND FLASH模式下:
U-Boot 2010.06 (Oct 07 2011 - 21:09:41)
DRAM: 64 MiB
Flash: 2 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
u-boot@SMDK2440 # nand info
Unknown command 'nand' - try 'help'
u-boot@SMDK2440 #
nand info不支持,说明关于NAND FLASH的命令还没有添加,这是对NAND Flash移植的第二部分。
第二阶段的移
植主要是C语言的移植,入口函数是 start_armboot 函数,其中它调用了board.c这个板
级密切相关的函数。其中的代码就有关于nand Flash 的宏等。
查找函数board.c
[root@Gong-Computer u-boot-2010.06]# find -name board.c
./arch/i386/lib/board.c
./arch/mips/lib/board.c
./arch/microblaze/lib/board.c
./arch/avr32/lib/board.c
./arch/arm/cpu/arm_cortexa8/omap3/board.c
./arch/arm/lib/board.c
./arch/blackfin/lib/board.c
./arch/sh/lib/board.c
./arch/sparc/lib/board.c
./arch/nios2/lib/board.c
./arch/powerpc/lib/board.c
./arch/m68k/lib/board.c
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/lib/board.
board.c board.o
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/lib/board.c
....
#if defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif
因此可知需要添加相应的宏
CONFIG_CMD_NAND,具体的后面会执行。
添加nand flash操作的相关函数。
[root@Gong-Computer u-boot-2010.06]# gedit drivers/mtd/nand/s3c2440_nand.c
#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);
twrph0 = 3; twrph1 = 0; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4)|(3<<2)|(1<<1)|(0<<0);
NFCONF = cfg;
//cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
cfg = (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;
nand->ecc.mode = NAND_ECC_SOFT;
return 0;
}
将加入的函数添加到可编译的范围里。
[root@Gong-Computer u-boot-2010.06]# vi drivers/mtd/nand/Makefile
/*将新添加的函数加入到编译范围之内*/
COBJS-y += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
添加默认命令:
[root@Gong-Computer u-boot-2010.06]# vi include/config_cmd_default.h
26 #define CONFIG_CMD_ITEST /* Integer (and string) test */
27
28 #define CONFIG_CMD_NAND /* NAND 相关的操作*/
29
30 #ifndef CONFIG_SYS_NO_FLASH
42 #define CONFIG_CMD_SAVEENV /* saveenv */
/*新添加的命令*/
43 #define CONFIG_CMD_EDITENV /* editenv */
44 #define CONFIG_CMD_ASKENV /* askenv */
当然在smdk2440.h中也可以添加nand flash的操作,但是CONFIG_CMD_NAND需要定义在较前的位
置,至少在CONFIG_CMD_SAVEENV的前面。原因不知道,不然会出错误。同时需要定义成这样:
#define CONFIG_CMD_NAND 1,其实本质上都是相同的。
在smdk2440.h中添加保存环境变量的相关参数
[root@Gong-Computer u-boot-2010.06]# vi include/configs/smdk2440.h
209 #if defined(CONFIG_CMD_NAND)
210 /*添加将环境变量保存到FLASH的宏定义*/
211 #define CONFIG_ENV_IS_IN_NAND 1 /*指明将环境变量保存在Nand Flash中*/
212 #define CONFIG_ENV_OFFSET 0x40000 /*将环境变量保存到nand 中的0x40000 位置*/
213 #define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector*/
214
215 /*这里的参数大小是根据实际芯片的扇区大小确定的,由于NAND FLASH中的u-boot占用了
前256K
216 *这需要根据实际的情况来分配大小。希望引起注意,不要前后考虑不一致。
217 */
218 /*将环境变量保存到NAND FLASH中,因此需要注释掉这两行*/
219 #else
220 #define CONFIG_ENV_IS_IN_FLASH 1
221 #define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
222 #endif
然后编译:
[root@Gong-Computer u-boot-2010.06]# make
make -C drivers/mtd/nand/
make[1]: Entering directory `/opt/u-boot-2010.06/drivers/mtd/nand'
Makefile:35: *** missing separator. Stop.
make[1]: Leaving directory `/opt/u-boot-2010.06/drivers/mtd/nand'
make: *** [drivers/mtd/nand/libnand.a] Error 2
这个错误说明是Makefile存在问题,而且在35行,发现原来是注释的符号错了,修改为
#/*将新添加的函数加入到编译范围之内*/
[root@Gong-Computer u-boot-2010.06]# make -d
........
-Wall -Wstrict-prototypes -fno-stack-protector \
-o nand.o nand.c -c
Putting child 0x93cc850 (nand.o) PID 18851 on the chain.
Live child 0x93cc850 (nand.o) PID 18851
nand.c:34: error: 'CONFIG_SYS_MAX_NAND_DEVICE' undeclared here (not in a function)
nand.c:37: error: 'CONFIG_SYS_NAND_BASE' undeclared here (not in a function)
Reaping losing child 0x93cc850 PID 18851
make[1]: *** [nand.o] Error 1
Removing child 0x93cc850 PID 18851 from chain.
make[1]: Leaving directory `/opt/u-boot-2010.06/drivers/mtd/nand'
Reaping losing child 0x98c6d58 PID 18690
make: *** [drivers/mtd/nand/libnand.a] Error 2
Removing child 0x98c6d58 PID 18690 from chain.
重新编译发现还是存在问题,这说明刚才的修改存在问题,而且问题比较严重,不知道怎么去修改,
需要查看Nand_flash相关的代码,这时候采用Source Insight实现代码的跟踪是比较有优势的。虽然
提示出来了,但是还是不是很清楚,通过查看源码同时比较其他外设更加丰富的实验板发现在板级的
头文件中smdk2440.h中需要添加上面缺少的两个宏。这两个值的具体值是什么还是需要查看源码,
或者对比以下其他开发板中的具体值,特别是 CONFIG_SYS_NAND_BASE的值需要参考修改。
添加宏如下:
236 #define CONFIG_SYS_MAX_NAND_DEVICE 1 /*芯片的个数*/
237 #define CONFIG_SYS_NAND_BASE 0x4E000000 /*是指控制器在内存中的基地址*/
重新编译和测试:
[root@Gong-Computer u-boot-2010.06]# make -d
Invoking recipe from Makefile:426 to update target `System.map'.
Putting child 0x99070f0 (System.map) PID 27598 on the chain.
Live child 0x99070f0 (System.map) PID 27598
Reaping winning child 0x99070f0 PID 27598
Removing child 0x99070f0 PID 27598 from chain.
Successfully remade target file `System.map'.
Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
下载到开发板的NAND FLASH,然后切换到NAND FLASH模式下。
##### Boot for Nor Flash Main Menu #####
##### EmbedSky TFTP download mode #####
[1] Download u-boot.bin to Nand Flash
[2] Download Eboot (eboot.nb0) to Nand Flash
[3] Download Linux Kernel (zImage.bin) to Nand Flash
[4] Download stepldr.nb1 to Nand Flash
[5] Set TFTP parameters(PC IP,TQ2440 IP,Mask IP...)
[7] Download Program (uCOS-II or TQ2440_Test) to SDRAM and Run it
[8] Boot the system
[9] Format the Nand Flash
[0] Set the boot parameters
[a] Download User Program (eg: uCOS-II or TQ2440_Test)
[b] Download LOGO Picture (.bin) to Nand Flash
[l] Set LCD Parameters
[o] Download u-boot to Nor Flash
[p] Test network (TQ2440 Ping PC's IP)
[r] Reboot u-boot
[t] Test Linux Image (zImage)
[q] Return main Menu
Enter your selection: 1
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.10.154; our IP address is 192.168.10.122
Filename 'u-boot.bin'.
Load address: 0x30000000
Loading: T ##########
done
Bytes transferred = 140064 (22320 hex)
NAND erase: device 0 offset 0x0, size 0x40000
Erasing at 0x20000 -- 100% complete.
OK
NAND write: device 0 offset 0x0, size 0x22320
Writing data at 0x22000 -- 100% complete.
140064 bytes written: OK
U-Boot 2010.06 (Oct 08 2011 - 10:44:25)
DRAM: 64 MiB
Flash: 2 MiB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Net: CS8900-0
Hit any key to stop autoboot: 0
Unknown command 'boot_zImage' - try 'help'
u-boot@SMDK2440 # nand info /*NAND 参数正确*/
Device 0: NAND 256MiB 3,3V 8-bit, sector size 128 KiB
u-boot@SMDK2440 # saveenv
Saving Environment to NAND... /*保存在可NAND*/
Erasing Nand...
Erasing at 0x40000 -- 100% complete.
Writing to Nand... done
u-boot@SMDK2440 #
以上说明Nand FLASH移植成功。
但是还是存在一个问题就是我们的Nor Flash将不会作为启动项,我们注释掉了nor Flash搬移的过程。
如果只是作为引导这个时候已经可以了,可以直接跳转到网络的移植方面。但是毕竟TQ 提供了双启
动,关于双启动的方法我暂时还在实验阶段,需要正在调试过程中。
双启动的原理网上的大牛Tekkaman 已经作出了解释,自己参看分析。
简单来说就是首先判断内存控制器的OM[1:0]的值判断在nand Flash模式还是在nor Flash中,具体的
判断方法就是读BWSCON [2:1]位。基本的框架如下所示,具体实现分析代码。
# define BWSCON 0x48000000
ldr r0,=BWSCON
ldr r0,[r0]
and r0,r0,#6
cmp r0, #0
bne relocate
///////////////////////////////////////////////////
//nand_boot
//Nand 搬移代码
////////////////////////////////////////////////////
relocate:
//nor_boot
//Nor 搬移代码
////////////////////////////////////////////////////
接测NAND FLASH中坏块的方法:
Samsung makes sure that either the 1st or 2nd page of every initial invalid block has non-FFh data at the
column address of 2048