转载自 http://blog.sina.com.cn/s/blog_79abea8a01012ruj.html
http://blog.163.com/tianjunqiang666@126/blog/static/87259119201243034639891/
在ftp://ftp.denx.de/pub/u-boot/中下载u-boot-2010.03,其实我之前用的是u-boot-2010.06,坑爹很久才发现,u-boot-2010.06是一个分界点,u-boot-2010.03是最后一个版本类似u-boot1.1.6.而u-boot-2010.06是一个新起点版本。
下载好u-boot-2010.03之后,解压缩,这里的一切我都是在win7系统下完成的。
1.进入u-boot-2010.03/board,把除samsung以外的文件夹删除。
2.进入u-boot-2010.03/cpu,把除arm1176以外的文件夹删除。
3.进入u-boot-2010.03\include,把asm-*(注意,仅仅是asm-开头的文件夹)中的,除了asm-arm和asm-generic以外的文件夹删除。
4.进入u-boot-2010.03\include\configs,只要留下smdk6400.h,其他的东西删除。
5.在u-boot-2010.03,把lib_*开头的文件夹,除了lib_arm和lib_generic以外的文件夹删除。
6.
现在把u-boot-2010.03放入到linux中,先配置:makesmdk6400_config,接着make。编译完成之后应该生成了u-boot.bin,其实现在什么都没有完成,我只是尝试了下原版u-boot2010.03能不能行。
我们先来看下删减之后的u-boot-2010.03的构架:
这里交大家一个指令:tree,怎么用呢?我也忘了,没关系,mantree。它会告诉你一切,我们找到我们需要的那条:
呵呵,那就是使用tree -L 深度
其中白色的是文件,蓝色的是目录,绿色的是可执行文件。
现在进入u-boot-2010.03\board\samsung,把除了smdk6400之外的文件夹删除,同时建立一个文件夹smdk6410,把smdk6400文件夹里面的东西复制到smdk6410文件夹中。进入smdk6410文件夹,把smdk6400.c改成smdk6410.c。
进入u-boot-2010.03\include\asm-arm,把除了arch-s3c64xx和proc-armv之外的文件夹删除。进入arch-s3c64xx,建立s3c6410.h,将s3c6400.h文件里面的程序原原本本复制到s3c6410.h。
进入根目录下的Makefile,这个我就不加详细分析,我想我也可能分析不过来。找到:
smdk6400_noUSB_config \
smdk6400_config : unconfig
@mkdir -p $(obj)include $(obj)board/samsung/smdk6400
@mkdir -p $(obj)nand_spl/board/samsung/smdk6400
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@if [ -z "$(findstring smdk6400_noUSB_config,$@)" ]; then \
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
$(MKCONFIG) $(@:_config=) arm arm1176 smdk6400 samsungs3c64xx; \
else \
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
$(MKCONFIG) $(@:_noUSB_config=) arm arm1176 smdk6400 samsung s3c64xx; \
fi
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
这个是smdk6400的配置,现在将它改成smdk6410的配置:
smdk6410_noUSB_config \
smdk6410_config : unconfig
@mkdir -p $(obj)include $(obj)board/samsung/smdk6410
@mkdir -p $(obj)nand_spl/board/samsung/smdk6410
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@if [ -z "$(findstring smdk6410_noUSB_config,$@)" ]; then \
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6410/config.tmp;\
$(MKCONFIG) $(@:_config=) arm arm1176 smdk6410 samsungs3c64xx; \
else \
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6410/config.tmp;\
$(MKCONFIG) $(@:_noUSB_config=) arm arm1176 smdk6410 samsung s3c64xx; \
fi
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
进入u-boot-2010.03\board\samsung\smdk6410,打开smdk6410.c,把#include<asm/arch/s3c6400.h>改成#include<asm/arch/s3c6410.h>。
把u-boot-2010.03中所有的*6400改成*6410。
这是第二版修改,我把下面这段代码做了适当修改:
#ifndef CONFIG_NAND_SPL
mov r0, #0
mcr p15, 0, r0, c7, c7, 0
mcr p15, 0, r0, c8, c7, 0
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
#endif
在start.S中,bllowlevel_init之前的代码都无需更改,直到这句话之后需要添加下面代码:
ldr r0, =0xff000fff
bic r1, pc, r0
ldr r2, _TEXT_BASE
bic r2, r2, r0
cmp r1, r2
beq after_copy
这段代码是判断到底是从nandflash中启动还是从ram中启动。
1.如果是从nandflash中启动,那么PC的值一定在8K之内。那么执行完bicr1,pc,r0之后,r1为0。_TEXT_BASE要么等于0x57e00000,要么等于0xC7e00000.那么执行完bicr2,r2,r0之后,r2为0x00e00000,那么不相等,则不跳转,下面应该就是copy_from_nand。
2.如果是从ram中启动,那么PC的值为0xx7e00000。那么执行完bicr1,pc,r0之后,r1为0x00e00000。_TEXT_BASE要么等于0x57e00000,要么等于0xC7e00000.那么执行完bicr2,r2,r0之后,r2为0x00e00000,那么相等,跳转到after_copy,也就是不需要copy。
承接上面分析,如果没有完成copy,则接下来就是copy_from_nand。
那么在beq after_copy后面添加:
#ifdef CONFIG_BOOT_NAND
mov r0, #0x1000
bl copy_from_nand
#endif
如果完成则会跳过这段代码,直接进入after_copy。
OK,在u-boot-2010.03\cpu\arm1176下面新建一个nand_cp.c文件:
#include <common.h>
#ifdef CONFIG_S3C64XX
#include <asm/io.h>
#include <linux/mtd/nand.h>
#include <asm/arch/s3c6410.h>
static int nandll_read_page (uchar *buf, ulong addr,intlarge_block)
{
int i;
int page_size = 512;
if (large_block==1)
page_size = 2048;
if (large_block==2)
page_size = 4096;
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READ0;
NFADDR_REG = 0;
if (large_block)
NFADDR_REG = 0;
NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;
if (large_block)
NFCMD_REG = NAND_CMD_READSTART;
NF_TRANSRnB();
for(i=0; i < page_size; i++)
{
*buf++=NFDATA8_REG;
}
NAND_DISABLE_CE();
return 0;
}
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
{
uchar *buf = (uchar *)dst_addr;
int i;
uint page_shift = 9;
if (large_block==1)
page_shift = 11;
if(large_block==2)
page_shift = 12;
if(large_block == 2)
{
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))
{
nandll_read_page(buf, i, large_block);
}
for (i = 4; i < (0x3c000>>page_shift);i++,buf+=(1<<page_shift))
{
nandll_read_page(buf, i, large_block);
}
}
else
{
for (i = 0; i < (0x3c000>>page_shift);i++,buf+=(1<<page_shift))
{
nandll_read_page(buf, i, large_block);
}
}
return 0;
}
int copy_uboot_to_ram(void)
{
int large_block = 0;
int i;
vu_char id;
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READID;
NFADDR_REG = 0x00;
for (i=0; i<200; i++);
id = NFDATA8_REG;
id = NFDATA8_REG;
if (id > 0x80)
large_block = 1;
if(id == 0xd5)
large_block = 2;
return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x3c000, large_block);
}
#endif
在u-boot-2010.03\cpu\arm1176的makefile中:
COBJS = cpu.o nand_cp.o
其中nand_cp.o是新加。
然后返回start.S,在:
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
这段代码之前添加上:
after_copy:
接着在:
#ifdef CONFIG_ENABLE_MMU
.globl theLastJump
theLastJump:
这段代码之前添加下面代码:
.globl copy_from_nand
copy_from_nand:
mov r10, lr
mov r9, r0
ldr sp, _TEXT_PHY_BASE
sub sp, sp, #12
mov fp, #0
mov r9, #0x1000
bl copy_uboot_to_ram
3: tst r0, #0x0
bne copy_failed
ldr r0, =0x0c000000
ldr r1, _TEXT_PHY_BASE
1: ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne compare_failed
subs r9, r9, #4
bne 1b
4: mov lr, r10
mov pc, lr
copy_failed:
nop
b copy_failed
compare_failed:
nop
b compare_failed
接着进入u-boot-2010.03\include\configs下面的smdk6410.h文件,
1.新添加下面代码,由于是宏定义,只要在smdk6410.h中,任何一个“可以”放置的地方放置都行,注意,是“可以”放置,自己体会什么意思:
#define virt_to_phys(x) virt_to_phy_smdk6410(x)
2.这句代码:
#define CONFIG_SYS_PROMPT "SMDK6400 # "
其中"SMDK6400 # "是由你自己进行修改,我改成了:"zhuzhaoqi#"这个随个人嘛。
3.注意下面这条宏定义:
#define PHYS_SDRAM_1_SIZE 0x08000000
这里是适应于内存为128MB的OK6410,但是我购买的OK6410—A内存为256MB,所以要对这句话进行修改:
#define PHYS_SDRAM_1_SIZE 0x1000 0000
为什么?
我们来分析一下:
我们知道2^10=1KB, 2^20=1MB,那么0x10000000=1*2^(4*7)=2^28 = (2^8)*(2^20) ,即为(2^8)MB,也就是256MB。
4.为了对号入座,我们就把nand_cp.c中用到的宏定义添加在
下面:
#define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
#define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
上面3个宏定义在前面的nand_cp.c中我已经分析了,这里就不多费口舌。
这里也是第二版修改,额外加上了如下改动:
1.第一版没有更改6410的ID号!
//#define MACH_TYPE 1270
#define MACH_TYPE 1626
将smdk6400的ID注释掉,添加smdk6410的ID号
2.更改内存的分配大小
//#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 1024 * 1024)
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024)
#define CONFIG_SYS_GBL_DATA_SIZE 128
3.修改bootdelay时间
#define CONFIG_BOOTDELAY 10
4.修改SDROM大小
//#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x7e00000)
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x9e00000)
5.时间的修改
//#define CONFIG_SYS_HZ 1000 // at PCLK 50MHz
#define CONFIG_SYS_HZ 1562500
6.堆栈大小的修改
//#define CONFIG_STACKSIZE 0x40000
#define CONFIG_STACKSIZE 0x80000
7.Nand flash每个块的大小修改
//#define PHYS_SDRAM_1_SIZE 0x08000000
#define PHYS_SDRAM_1_SIZE 0x10000000
8.Total Size of Environment Sector 的修改
//#define CONFIG_ENV_SIZE 0x4000
#define CONFIG_ENV_SIZE 0x80000
9.CONFIG_BOOTCOMMAND的修改
#define CONFIG_BOOTCOMMAND "nand read 0x50018000 0x60000 0x1c0000;" \
"bootm 0x50018000"
修改为:
#define CONFIG_BOOTCOMMAND "nand read 0x50008000 0x100000 0x500000;" \
"bootm 0x50018000"
10.CONFIG_ENV_OFFSET的修改:
#define CONFIG_ENV_OFFSET 0x0080000
11.Nand flash每一页大小的修改:
//#define CONFIG_SYS_NAND_PAGE_SIZE 2048
#define CONFIG_SYS_NAND_PAGE_SIZE 4096
12.Nand flash每一块大小的修改:
//#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024)
#define CONFIG_SYS_NAND_BLOCK_SIZE (512 * 1024)
13.校验位
//#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_COUNT 128
在这里还需要一步完成,这里也是第二版本添加:
1.在u-boot-nand.lds中添加:
{
cpu/arm1176/start.o (.text)
cpu/arm1176/s3c64xx/cpu_init.o (.text)
board/samsung/smdk6410/lowlevel_init.o (.text)
cpu/arm1176/nand_cp.o (.text)
lib_arm/board.o (.text)
*(.text)
}
2.在u-boot.lds中添加:
{
cpu/arm1176/start.o (.text)
cpu/arm1176/s3c64xx/cpu_init.o (.text)
board/samsung/smdk6410/lowlevel_init.o (.text)
cpu/arm1176/nand_cp.o (.text)
lib_arm/board.o (.text)
*(.text)
}
3.删除nand_spl\board除去samsung文件夹以外的文件夹,进入samsung,复制一个smdk6410.
进入makefile:
COBJS = nand_boot.o nand_ecc.o s3c64xx.o nand_cp.o
在下面代码
# from SoC directory
$(obj)cpu_init.S:
@rm -f $@
@ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@
之后添加
$(obj)nand_cp.c:
@rm -f $@
@ln -s $(TOPDIR)/cpu/arm1176/nand_cp.c $@
在编译之前还有一个地方需要修改:
在lowlevel_init.S修改LED灯的测试代码,这个参考6410手册进行修改。
配置,编译,生成u-boot.bin
放进去OK6410开发版,可以看到下面效果:
于是乎,OK,u-boot-2010.03的移植就完成了第一步。
接下来就是网卡了。
U-boot-2010.03默认的网卡支持是CS8900,但是OK6410使用的是DM9000.
在smdk6410.h中将CS8900的宏定义注释掉:
//#define CONFIG_NET_MULTI
//#define CONFIG_CS8900
//#define CONFIG_CS8900_BASE 0x18800300
//#define CONFIG_CS8900_BUS16
然后添加DM9000网卡的宏定义:
#define CONFIG_NET_MULTI 1
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_dm9000
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x18800300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#define CONFIG_DM9000_USE_16BIT
#define CONFIG_ETHADDR 00:40:5c:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 172.16.114.20
#define CONFIG_SERVERIP 172.16.114.10
#define CONFIG_GATEWAYIP 172.16.114.1
//#define CONFIG_DM9000_DEBUG
上面的IP和网关、子网掩码等根据自己的具体情况进行修改。
接着打开u-boot-2010.03/net/eth.c,并且进入到函数int eth_initialize(bd_t*bis)中,在:
#if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx)
mv6446x_eth_initialize(bis);
#endif
后面添加下面代码:
#if defined(CONFIG_DRIVER_DM9000)
dm9000_initialize(bis);
#endif
同样在u-boot-2010.03/net/net.c,
1.将//# define ARP_TIMEOUT 5000UL
修改成:
# define ARP_TIMEOUT 5
2.将if ((t - NetArpWaitTimerStart)>ARP_TIMEOUT)
修改成:
if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT*CONFIG_SYS_HZ)
3.将//NetSetTimeout (10000UL, PingTimeout);
修改成:
NetSetTimeout (10*CONFIG_SYS_HZ, PingTimeout);
接着进入u-boot-2010.03/net/tftp.c,找到void
TftpStart (void)函数,用#if 0 #endif注释掉下面的程序:
#if 0
if ((ep = getenv("tftpblocksize")) != NULL)
TftpBlkSizeOption = simple_strtol(ep, NULL, 10);
if ((ep = getenv("tftptimeout")) != NULL)
TftpTimeoutMSecs = simple_strtol(ep, NULL, 10);
if (TftpTimeoutMSecs < 1000) {
printf("TFTP timeout (%ld ms) too low, "
"set minimum = 1000 ms\n",
TftpTimeoutMSecs);
TftpTimeoutMSecs = 1000;
}
debug("TFTP blocksize = %i, timeout = %ld ms\n",
TftpBlkSizeOption, TftpTimeoutMSecs);
#endif
网卡驱动终究完成。编译:
放进去OK6410效果:
上图即为移植好网卡后的效果图。
这是我移植u-boot的第一个版本,日后会渐渐在这份资料上进行完善。下一次更新在半月之后。
进入dm9000x.c,找到staticintdm9000_rx(structeth_device*netdev)函数,把for(;;){}修改成do{}while.
在do之前添加:
DM9000_ior(DM9000_MRRH);
DM9000_ior(DM9000_MRRL);
static void dm9000_halt(struct eth_device *netdev)
{
DM9000_DBG("%s\n", __func__);
//phy_write(0, 0x8000);
//DM9000_iow(DM9000_GPR, 0x01);
//DM9000_iow(DM9000_IMR, 0x80);
//DM9000_iow(DM9000_RCR, 0x00);
}
再把上面的//后面的程序屏蔽
这里是网络ping通之后的效果:
Nand flash读写:
nand flash的控制都是这个套路,因为这就是硬件协议,先使能芯片->发送命令->发送地址序列->读或写数据寄存器->判断准备就绪状态->禁止芯片,这是对nandflash操作的大体过程,根据发送命令的不同还有些区别。
在nand_cp.c中有这么一段代码很有意思,现在拿出来分析一下:
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))
{
nandll_read_page(buf, i, large_block);
}
for (i = 4; i < (0x3c000>>page_shift);i++,buf+=(1<<page_shift))
{
nandll_read_page(buf, i, large_block);
}
首先我们来看下buf是什么?
uchar *buf = (uchar *)dst_addr;
dst_addr又是什么?
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
我们再看一下下面这条程序:
return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x3c000, large_block);
也就是说buf的地址就是CONFIG_SYS_PHY_UBOOT_BASE。前面我们就分析过CONFIG_SYS_PHY_UBOOT_BASE =0x57e00000.
好了,我们现在开始分析第个for语句:
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))
{
nandll_read_page(buf, i, large_block);
}
i = 0 ,buf = buf + 2^(12-1) = buf+2K;
注意,每次是2K的操作,单独一句不奇怪,Ok,我们接着看第二个for语句。
for (i = 4; i < (0x3c000>>page_shift); i++,buf+=(1<<page_shift))
{
nandll_read_page(buf, i, large_block);
但是执行四次之后每次是4K的操作,为什么?之前刚好执行了8K!!!
关键的8K代码不是在K9GAG08U0D型号(每页4K)的前两页存放,也不是在K9GAG08U0E型号(每页8K)的第一页存放,而是在K9GAG08U0E型号或者K9GAG08U0D型号的前四页中存放的,前四页分为每页2K,总共8K,这是由s3c6410芯片本身所规定的。这8K字节外后面的数据就是按实际的页数存放了,K9GAG08U0D型号每页存放4K字节,K9GAG08U0E型号每页存放8K字节。
再者,进入nand.ids,作如下修改:
//{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS},
{"NAND 2GiB 3,3V 8-bit", 0xD5, 4096, 2048, 512*1024,LP_OPTIONS},
我把生成的u-boot烧写到OK6410当中运行,在u-boot上:
Set bootdelay 20
Sav
按理说我复位启动之后应该是20S了,但是,这是我在启动瞬间接下来的图:
说明我们的环境变量没有储存在nand flash,why!!!
没办法,找吧!
1.将s3c6410.h中的:
#define DMC1_MEM_CFG 0x00010012
和
#define DMC1_CHIP0_CFG 0x150F8
修改成如下:
#define DMC1_MEM_CFG 0x0001001a
和
#define DMC1_CHIP0_CFG 0x150F0
2.在include/linux/mtd/mtd.h:
将结构体struct erase_info{}中的
//uint64_t addr;
//uint64_t len;
//uint64_t fail_addr;
改成:
u_int32_t addr;
u_int32_t len;
u_int32_t fail_addr;
将结构体struct mtd_erase_region_info{}中的
//uint64_t offset;
改成:
u_int32_t offset;
3.在int env_init(void):
if (!crc1_ok && !crc2_ok) {
gd->env_addr = 0;
gd->env_valid = 0;
return 0;
} else if (crc1_ok && !crc2_ok) {
gd->env_valid = 1;
}
改成:
if (!crc1_ok && !crc2_ok) {
//gd->env_addr = 0;
//gd->env_valid = 0;
gd->env_valid = 1;
return 0;
} else if (crc1_ok && !crc2_ok) {
gd->env_valid = 1;
}
其实这步是违规的。但是只有这样强制性才能达到我想要的目标,至于为什么,请求高手指点。编译运行,OK!
按理说,u-boot的移植到此就应该结束了,但是什么都要智能化,那么现在我们就完成智能化。
U-boot有许多指令,nandinfo,set等等。现在我们来给u-boot添加我们想要的指令。
我们进入include/command.h头文件中 :
可以找到 cmd_tbl_t这个结构体,u-boot中每个命令都用这样的一个结构体来描述,类型定义如下:
typedef struct cmd_tbl_s cmd_tbl_t;
struct cmd_tbl_s {
char*name;//命令的名称
intmaxargs;//最多支持的参数的个数
intrepeatable;//是否可重复执行
int(*cmd)(structcmd_tbl_s*,int, int, char *const[]);//命令对应的处理函数
char*usage;//命令简要使用信息
char*help;//命令详细帮助信息
}
在common文件夹下面新建一个cmd_hello.c文件:
#include <common.h>
#include <command.h>
int do_hello(cmd_tbl_t *cmdtp, int flag, int argc,char*constargv[])
{
printf("mynameiszhuzhaoqi!\n");
return0;
}
U_BOOT_CMD(hello, CONFIG_SYS_MAXARGS, 1, do_hello, "usage info", "help info");
然后在common/Makefile中的#command添加如下内容: COBJS-$(CONFIG_CMD_TEST)+=cmd_hello.o
Ok,现在编译、运行:
我现在小试hello的指令,好了,我现在添加其他的指令。
我们现在在cmd_nand.c的基础上添加一个自动下载u-boot到nand flash中的指令,这个是第二版本新加。
进入cmd_nand.c中,在:
if (strcmp(cmd, "biterr") == 0) {
return 1;
}
之后添加:
if(strcmp(cmd,"uboot")==0)
{
printf("Re-program the u-boot to nand flash\n");
if (argc < 3)
goto usage;
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
run_command ("nand erase 0 100000", 0);
//printf("nand erase 0 100000......\n");
size = 0x1000;
puts("\nwrite u-boot to nand flash......1 \n");
for (i = 0; i < 4; i++, addr += 0x800)
{
nand_write_skip_bad(nand, size*i, &size, (u_char *)(addr));
}
puts("write u-boot to nand flash......2 \n");
for(i=4; i< 64; i++, addr += 0x1000)
{
nand_write_skip_bad(nand, size*i, &size, (u_char *)(addr));
}
return 0;
}
加上之后,编译运行:
这就是我们添加nand uboot 之后的效果。
接下来就是内核的引导了。这个就要根据内核来编译了。所以引导内核linux不同也会有所细微不同。
1.由于uboot只能引导uImage,因此需要把编译成的zImage转换成uImage,先进入u-boot根目录下,把tools/下mkimage复制到虚拟机/bin目录下,然后进入到linux-2.6.36/下输入指令:makeuImage。
2.#defineCONFIG_BOOTARGS "root=/dev/mtdblock2 rootfstype=cramfs console=ttySAC0,115200" 是在smdk6410.h里面。这要根据linux内核mach-ok6410.c中的:
static struct mtd_partition ok6410_nand_part[] = {
{
.name = "Bootloader",
.offset = 0,
.size = (1 * SZ_1M),
.mask_flags = MTD_CAP_NANDFLASH,
},
{
.name = "Kernel",
.offset = (1 * SZ_1M),
.size = (5*SZ_1M) ,
.mask_flags = MTD_CAP_NANDFLASH,
},
{
.name = "User",
.offset = (6 * SZ_1M),
.size = (120*SZ_1M) ,
},
{
.name = "File System",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
分区而定。否则就算用这个可行的u-boot还是无法引导飞凌公司提供的编译好了的linux内核。