轉載自 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*const argv[])
{
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內核。