1.讀readme獲取信息 1.1 由Building the Software可知,需修改頂層makefile,指定架構和編譯器 ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE ?= arm-linux- endif ARCH = arm CROSS_COMPIL ...
1.讀readme獲取信息
1.1 由Building the Software可知,需修改頂層makefile,指定架構和編譯器
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?= arm-linux-
endif
ARCH = arm
CROSS_COMPILE = arm-linux-
2.新建一個單板
cd board/samsung/
cp smdk2410 smdk2440 -rf
cd ../../include/configs/
cp smdk2410.h smdk2440.h
3.仿造smdk2410修改文件
具體做法為
grep "smdk2410" * -nR建立並修改相應的文件
4.實驗並燒寫,查看結果
make smdk2440_config
make
5.下載到開發板後沒有任何輸出,閱讀代碼發現不足
在u-boot-2016.11\arch\arm\cpu\arm920t\start.S出了問題沒有對MPLL
進行初始化/設置時鐘,而是在board_init_f中board_early_init_f初始化
的,但是之前是按照64MHz設置的,而現在的2440只工作在12MHz,這樣是
無法正常工作,所以應該把board_early_init_f里對MPLL的設置給註釋掉,
在start.S關閉看門狗後進行時鐘的設置。
5.2處理措施:
#if 0
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#else
/* 2. 設置時鐘 400MHz */
ldr r0, =0x4c000014
// mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0]
/* 如果HDIVN非0,CPU的匯流排模式應該從“fast bus mode”變為“asynchronous bus mode” */
mrc p15, 0, r1, c1, c0, 0 /* 讀出控制寄存器 */
orr r1, r1, #0xc0000000 /* 設置為“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 寫入控制寄存器 */
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
/* MPLLCON = S3C2440_MPLL_400MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
/* 啟動ICACHE */
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 @ write it back
#endif
6.
①依照上述下載到2440開發板,串口輸出亂碼,這表示2440工作了,這時候出現
亂碼應該是串口方面的問題,在board_init_f函數中調用了init_sequence_f數組
裡面有一個串口初始化serial_init,點進去,裡面有個get_current函數,再進
裡面default_serial_console函數,再進,在這個函數所在的c文件(serial_s3c24x0.c)
中有個_serial_setbrg函數中裡面有個get_PCLK函數進去該函數中有這麼一句
”#ifdef CONFIG_S3C2440”但是這個巨集沒有被定義,這個代表定義它就支持了2440,我們就
在include/configs/smdk2440.h中定義一下就可以了.然後再重新編譯,編譯出來的u-boot_04.bin
下載到2440中我們就可以看到串口列印出信息了
②改完後編譯,燒寫,串口有輸出了,但是亂碼,估計是波特率的問題。分析代碼
board_init_r
init_sequence_r
initr_serial
serial_initialize
s3c24xx_serial_initialize
serial_register(&s3c24xx_serial0_device)
s3c24xx_serial0_device
INIT_S3C_SERIAL_STRUCTURE
s3serial##port##_setbrg
serial_setbrg_dev
_serial_setbrg
get_PCLK
get_HCLK(#ifdef CONFIG_S3C2440)
7.支持NOR FLASH
board_init_r
init_sequence_r
initr_flash
flash_init
if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))
flash_get_size(cfi_flash_bank_addr(i), i);
//用老方法檢測是否識別出來,否則就用新方法
為什麼老方法無法識別出nor flash?
flash_detect_legacy
jedec_flash_match
jedec_table//該數組裡沒有我們需要的nor flash的型號和參數,需要手動輸入
{
.mfr_id = (u16)MX_MANUFACT,
.dev_id = 0x2249,
.name = "MX29LV160D",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x10000, 31),
ERASEINFO(0x08000, 1),
ERASEINFO(0x02000, 2),
ERASEINFO(0x04000, 1),
}
},
測試下norflash能否正確讀寫,用以下u-boot命令:
cp.b 0 30000000 80
cmp.b 0 30000000 80
發現讀norflash沒有問題。再用以下幾條命令測試寫norflash:
mw.b 30000000 12 3
protect off all
erase 0 ffff
cp.b 30000000 0 3
md.b 0 3;
發現也是121212;因此寫norflash成功,至此u-boot已經支持JZ2440開發板的nor flash;
8.支持nand flash
支持了norflash後,發現nandflash未識別出來,啟動uboot顯示NAND: 0 Byte。在代碼
中搜索"NAND:",定位到common目錄中的board_r.c的initr_nand函數:
nand_init
nand_init_chip
board_nand_init
設置nand_chip結構體, 提供底層的操作函數
nand_scan
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip;
chip->cmdfunc = nand_command;
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_command() // 即可以用來發命令,也可以用來發列地址(頁內地址)、行地址(哪一頁)
chip->cmd_ctrl
s3c2440_hwcontrol
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);
board_nand_init函數主要與單板有關的初始化,uboot的開發人員已經把與單板無關的一些
協議設置完成了,而把與單板有關的初始化單獨列為一層,我們需要做的僅僅是把單板相關的
這一層移植即可。因此這裡主要關註board_nand_init函數。我們的board_nand_init函數在
drivers/mtd/nand/s3c2410_nand.c中定義了。進入其中仔細分析代碼,發現對nfconf寄存器
的初始化,2410的設置並不適用於2440,於是修改代碼如下:
//cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
writel(cfg, &nand_reg->nfconf);
#define S3C2410_NFCONF_TACLS(x) ((x)<<12)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<4)
往下看,後面設置了2410的nandflash的底層函數,其中selcet_chip被設置為NULL了,我們在
nand_scan里往下看,nand_scan_ident到nand_set_defaults,如果某個底層函數是空,則會
為其分配一個預設的函數,其中的預設的select_chip函數並不完整,不能用,並且後面的代碼
調用到select_chip函數,因此這裡需要我們自己寫一個select_chip函數。
在s3c2410_nand.c中定義如下:
static void s3c24x0_nandselect(struct mtd_info *mtd, int chipnr)
{
struct s3c24x0_nand *nand_reg = s3c24x0_get_base_nand();
switch (chipnr) {
case -1:
writel(readl(&nand_reg->nfcont) | (1 << 1),&nand_reg->nfcont);
break;
case 0:
writel(readl(&nand_reg->nfcont) & ~(1 << 1),&nand_reg->nfcont);
break;
default:
BUG();
}
}
在board_nand_init函數中設置select_chip函數
nand->select_chip = s3c24x0_nandselect;
繼續往下分析,發現s3c24x0_hwcontrol函數不適用於2440,修改如下:
static void s3c24x0_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong)nand;
if (!(ctrl & NAND_CLE))
IO_ADDR_W |= S3C2410_ADDR_NCLE;//NFADDR
if (!(ctrl & NAND_ALE))
IO_ADDR_W |= S3C2410_ADDR_NALE;//NFCMD
chip->IO_ADDR_W = (void *)IO_ADDR_W;
if (ctrl & NAND_NCE)
writel(readl(&nand->nfcont) & ~(1<<1),
&nand->nfcont);//chip select
else
writel(readl(&nand->nfcont) | (1<<1),
&nand->nfcont);//deselcet
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
else //若cmd = NAND_CMD_NONE,寫地址要恢復為nfdata
chip->IO_ADDR_W = (void *)&nand->nfdata;
}
這個s3c24x0_hwcontrol函數可以根據crtl值的不同更改寫指針chip->IO_ADDR_W,
從而實現既能寫地址,又能寫命令,當crtl & NAND_CRTL_CHANGE=1時,chip->ADDR_W
就會被賦一次值。在nand_set_defaults中,chip->cmdfunc = nand_command,這個
函數里會多次調用chip->cmd_crtl(即我們的s3c24x0_hwcontrol函數)來實現發命令
和發地址。由於s3c2410_nand.c中未定義chip->cmdfunc,就會使用預設的nand_command。
這裡最好將nand_command改為 nand_command_lp,因為我們的nandflash是大頁的,每頁數據
有2K+64個位元組。仔細閱讀nand_command_lp你就會瞭解s3c24x0_hwcontrol應該實現的功能。
在nand_command_lp中,我們發現每個階段調用chip->cmd_crtl之後,最後都會調用
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE)(寫地址結束後調用一次,寫命令結束後調用一次),
仔細思考你就會想到,chip->IO_ADDR_W在board_nand_init中是被初始化為指向nfdata的,
如果我們調用完s3c24x0_hwcontrol,chip->IO_ADDR_W是指向nfaddr或nfcmd,是否要將其還原呢
,否則下次如果要想寫數據不是會出錯嗎(寫數據不用調用chip->cmd_ctrl),
因此chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE)的用意應該是還原
chip->IO_ADDR_W為nfdata,所以上面的s3c24x0_hwcontrol的最後我加上了個else分支。經過實驗,
不加這一句,nandflash讀寫會出錯。
另外,S3C2410_ADDR_NCLE和S3C2410_ADDR_NALE兩個巨集要修改為如下:
#define S3C2410_ADDR_NALE 8
#define S3C2410_ADDR_NCLE 0xC
這裡使用到了NFCONT寄存器,而2410並無該寄存器,之前未對其進行初始化,因此在
board_nand_init中要對該寄存器進行初始化設置:
/* 初始化ECC,禁止片選,使能NAND Flash控制器 */
writel((1<<4)|(1<<1)|(1<<0),&nand_reg->nfcont);
同時,s3c24x0_nand結構體中由於原來定義了CONFIG_S3C2410巨集,導致沒有NFCONT等寄存器,
因此在smdk2410.h中去掉該巨集。編譯,燒寫到開發板,識別出nandflash為256M。我們再試試
Nandflash的讀寫。首先試試寫nandflash,用以下命令:
nand erase 0 4
mw.l 30000000 12345678
nand write 30000000 0 4
nand dump 0
發現nandflash寫入12345678成功。然後再試讀nandflash,使用命令:
mw.l 30000000 22222222
md.l 30000000
nand read 30000000 0 4
md.l 30000000
發現成功讀出12345678。至此u-boot已經成功支持JZ2440的nandflash。
9.支持DM9000
啟動uboot,列印出Net: CS8900-0,而我們的網卡是DM9000,於是在代碼中搜索“Net:”,
定位到common/board_r.c的initr_net函數,一路追蹤eth_initialize,eth_common_init,
一直到board\samsung\smdk2410\smdk2410.c的board_eth_init函數:
int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_CS8900
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
return rc;
}
這裡是對CS8900進行了初始化,我們要對DM9000進行初始化,通過查看
drivers/net/Makefile,發現要包含dm9000x.c的文件,要定義CONFIG_DRIVER_DM9000
這個巨集,我們也要註釋掉CONFIG_CS8900巨集。同時查看dm9000x.c,裡面有一個
dm9000_initialize函數,於是仿照cs8900來寫dm9000的初始化函數。
int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_CS8900
rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef CONFIG_DRIVER_DM9000
rc = dm9000_initialize(bis);
#endif
return rc;
}
配置文件smdk2410.h修改如下:
//#define CONFIG_CS8900 /* we have a CS8900 on-board */
//#define CONFIG_CS8900_BASE 0x19000300
//#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#define CONFIG_DRIVER_DM9000
保存,編譯,提示一大堆錯誤,提示dm9000x.c中的'DM9000_DATA' undeclared, 'DM9000_IO' undeclared等等,
結合上面的CS8900的一些巨集,看來這些巨集需要我們自己在smdk2410.h中定義,在linux中使用grep "DM9000_DATA" * -nR
命令搜索,看看其他板子的配置文件是如何定義這些巨集的,可以適當參考下,結合原理圖和2440手冊,smdk.h中定義如下:
#define CONFIG_DRIVER_DM9000
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#define CONFIG_DM9000_USE_16BIT 1
第四行之所以加4是因為DM9000上的CMD引腳接到了LADDR2上。
編譯,下載到開發板,提示錯誤Error: dm9000 address not set.
在代碼中搜索“address not set”,有兩個函數會列印這句話,分別是net/eth.c里的
eth_post_probe函數和eth_write_hwaddr函數。這個eth_post_probe函數是uboot里網卡
驅動的probe函數,而eth_write_hwaddr會在eth_initialize里被調用,因此這裡應該是
eth_write_hwaddr列印出來的。閱讀這個函數的代碼,發現應該是未設置ethaddr即網卡
的MAC地址導致報錯。進入到eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr)里分析:
int eth_getenv_enetaddr_by_index(const char *base_name, int index,
uchar *enetaddr)
{
char enetvar[32];
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
return eth_getenv_enetaddr(enetvar, enetaddr);
}
分析得知,這個函數最終將存放MAC地址的環境變數的值存入env_enetaddr數組中,那麼這個
環境變數名稱由
sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index)確定。在eth_initialize里eth_write_hwaddr是這樣被調用的:
eth_write_hwaddr(dev, "eth", dev->index)。上面的basename應該對應於"eth"。結合上面的sprintf函數,如果index函數存在,則
環境變數名稱為eth<index>addr,否則為ethaddr。這裡index的值即為eth_write_hwaddr(dev, "eth", dev->index)傳入的dev->index,
在eth.c中搜索dev->index,看在哪裡設置它的值。結果發現eth_register里會設置:
int eth_register(struct eth_device *dev)
{
struct eth_device *d;
static int index;
assert(strlen(dev->name) < sizeof(dev->name));
if (!eth_devices) {
eth_devices = dev;
eth_current = dev;
eth_current_changed();
} else {
for (d = eth_devices; d->next != eth_devices; d = d->next)
;
d->next = dev;
}
dev->state = ETH_STATE_INIT;
dev->next = eth_devices;
dev->index = index++;
return 0;
}
那麼這個函數什麼時候會被調用呢,搜索發現每一款網卡的文件里會調用這個函數來註冊網卡,我們的DM9000x.c里也有,我們只有一個網卡,
因此只會調用一次,index是靜態變數,未賦初始值則預設初始值為0,因此dev->index = index++(註意計算順序),dec->index = 0,所以
環境變數名稱為ethaddr。所以我們需要定義一個名為ethaddr環境變數。在include/env_default.h中有預設環境變數的設置,我們在其中
加入ethaddr環境變數的預設值,這個值我是參照電腦網卡MAC地址隨便寫的。
#elif defined(DEFAULT_ENV_INSTANCE_STATIC)
static char default_environment[] = {
#else
const uchar default_environment[] = {
#endif
#ifdef CONFIG_ETHADDR
"ethaddr=" CONFIG_ETHADDR "\0"
#endif
#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
#endif
在smdk2410.h中設置CONFIG_ETHADDR巨集:
#define CONFIG_ETHADDR "00:0c:29:91:dc:5f"
保存,編譯,燒寫,啟動Uboot,網卡正常啟動。設置一下開發板ip:set ipaddr 192.168.0.2。網線連接開發板和路由器,ping一下主機ip:
ping 192.168.0.100,能夠Ping通。再試試能不能用tftp下載文件,
set serverip 192.168.0.100
tftp 30000000 u-boot.bin
使用tftp下載文件也成功,至此,DM9000網卡已經支持。
10.設置nand分區
在下載內核或文件系統時,我們可以直接在命令中寫明燒到nandflash
的具體地址,但較麻煩,我們可以給nandflash分區,這樣就可直接寫
燒到那個分區就行了,較為方便。如何設置呢?首先我們在uboot中輸入
mtdparts命令,看看預設的分區,結果提示mtdids not defined, no default present。
搜索"mtdids not defined",定位到common/cmd_mtdparts.c的mtdparts_init函數中,
分析發現是mtdids_default為空。mtdids以及另一個重要的變數mtdparts定義如下:
#if defined(MTDIDS_DEFAULT)
static const char *const mtdids_default = MTDIDS_DEFAULT;
#else
$ static const char *const mtdids_default = NULL;
#endif
#if defined(MTDPARTS_DEFAULT)
static const char *const mtdparts_default = MTDPARTS_DEFAULT;
#else
static const char *const mtdparts_default = NULL;
#endif
因此,我們需要在smdk2410.h中定義MTDIDS_DEFAULT,MTDPARTS_DEFAULT這兩個巨集。如何定義這兩個巨集呢,cmd_mtdparts.c中註釋里有例子示範了:
/* Examples:
*
* 1 NOR Flash, with 1 single writable partition:
* mtdids=nor0=edb7312-nor
* mtdparts=mtdparts=edb7312-nor:-
*
* 1 NOR Flash with 2 partitions, 1 NAND with one
* mtdids=nor0=edb7312-nor,nand0=edb7312-nand
* mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
*
*/
結合例子和其他開發板的配置文件,我們的定義如下:
#define MTDIDS_DEFAULT "nand0=s3c2440-nand.0"
#define MTDPARTS_DEFAULT "mtdparts=s3c2440-nand.0:256k(bootloader),"\
"128k(params),2m(kernel),"\
"-(rootfs)"
保存,編譯,燒寫。啟動u-boot後執行mtdparts命令,提示mtdparts variable not set, see 'help mtdparts',no partitions defined
那就執行help mtdparts命令看看,發現這麼一句:mtdparts default - reset partition table to defaults
可能要執行一下mtdparts default,執行後發現不再提示錯誤。但總不能每次都要手動執行一次命令吧。於是,我們在代碼里執行這麼一個命令。
在board_r.c的run_main_loop里修改如下:
static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
sandbox_main_loop_init();
#endif
/* main_loop() can return to retry autoboot, if so just run it again */
run_command("mtdparts default",0);//添加這一行代碼
for (;;)
main_loop();
return 0;
編譯燒寫後,啟動u-boot執行mtdparts命令,不再提示錯誤,直接列出了分區,我們試著往kernel分區里燒寫uImage,同時要想啟動內核,
必須要設置預設參數bootargs和bootcmd,根據environment.h文件,我們要在smdk2410.h里設置CONFIG_BOOTARGS和CONFIG_BOOTCOMMAND兩個巨集,如下:
#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
#define CONFIG_BOOTCOMMAND "nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0"
編譯燒寫,啟動u-boot,使用tftp下載uImage到30000000,使用下麵的命令
nand erase.chip
nand write.jffs2 30000000 kernel 1c08e8
下載內核到kernel分區成功,並且已經可以啟動內核了。
之前我們設置環境變數,都未執行save命令,因為我們還未設置環境變數保存地址,現在我們想讓環境變數保存在我們設置的params分區上。
搜索saveenv函數,發現env_flash.c和env_nand.c都有這個函數,通過查看common/Makefile發現要通過定義CONFIG_ENV_IS_IN_NAND才能包含env_nand.c,
從而將環境變數保存在nandflash上。同時還要設置CMD_SAVEENV,CONFIG_ENV_RANGE,CONFIG_ENV_OFFSET等巨集,修改配置文件如下:
#define CONFIG_ETHADDR "00:0c:29:91:dc:5f"
//#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
//#define CONFIG_ENV_IS_IN_FLASH
//#define CONFIG_ENV_SIZE 0x10000
#define CMD_SAVEENV
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_SIZE 0x20000
#define CONFIG_ENV_OFFSET 0
編譯燒寫後,執行命令:
set ipaddr 192.168.0.2
set serverip 192.168.0.100
save
然後reset,發現原來一直提示的一個警告Warning - bad CRC, using default environment已經沒了,因為我們自己保存了環境變數。print一下,環境變數和我們設置的一樣。
11.
之前我們的u-boot已經能夠啟動內核了,現在我們試試能不能掛載文件系統,首先先下載jffs2格式的文件系統到30000000。然後使用命令
nand write.jffs2 30000000 rootfs 59ad78燒寫到nandflash的rootfs分區,在bootargs環境變數里添加rootfstype=jffs2,然後重啟開發板,
發現內核能夠掛載文件系統,證明我們的uboot支持燒寫jffs2文件系統。
再試試yaffs2文件系統,同樣下載到30000000,使用nand write.yaffs2 或nand write.yaffs發現都沒有這個命令,於是我們進入nand的命令文件common/cmd_nand.c,
在do_nand函數里,有nand read或write的代碼,而其中有對jffs2的支持,卻並沒有對yaffs2的支持。以前的老版本uboot是有對yaffs文件系統燒寫的支持的,於是我們參考老版本
的uboot代碼,在do_nand函數里的nand write/read部分加上一段代碼,如下:
#ifdef CONFIG_CMD_NAND_TRIMFFS
} else if (!strcmp(s, ".trimffs")) {
if (read) {
printf("Unknown nand command suffix '%s'\n", s);
return 1;
}
ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
maxsize, (u_char *)addr,
WITH_DROP_FFS | WITH_WR_VERIFY);
#endif
#ifdef CONFIG_CMD_NAND_YAFFS
} else if (!strcmp(s, ".yaffs")) {
if (read) {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
}
ret = nand_write_skip_bad(nand, off, &rwsize,NULL,//這裡參數和老版比要修改下
maxsize,(u_char *)addr,
WITH_YAFFS_OOB);
#endif
在nand_help_text[]里添加nand write.yaffs的幫助信息:
"nand read.raw - addr off|partition [count]\n"
"nand write.raw - addr off|partition [count]\n"
" Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
#ifdef CONFIG_CMD_NAND_YAFFS
"nand write.yaffs - addr off|partition size\n"
" write 'size' bytes starting at offset 'off' with yaffs format\n"
" from memory address 'addr', skipping bad blocks.\n"
#endif
nand_write_skip_bad函數內部也要修改:
if (actual)
*actual = 0;
#ifdef CONFIG_CMD_NAND_YAFFS
if (flags & WITH_YAFFS_OOB) {
if (flags & ~WITH_YAFFS_OOB)
return -EINVAL;
int pages;
pages = nand->erasesize / nand->writesize;
blocksize = (pages * nand->oobsize) + nand->erasesize;
if (*length % (nand->writesize + nand->oobsize)) {
printf ("Attempt to write incomplete page"
" in yaffs mode\n");
return -EINVAL;
}
} else
#endif
{
blocksize = nand->erasesize;