移植u-boot-1.1.6(原创)

时间:2021-11-01 09:55:18

#u-boot:u-boot-1.1.6
#server:ubuntu 12.04
#gcc: arm-linux-gcc -4.3.2
#

一、建立单板
1> /board/smdk2410 : cp /board/smdk2410 /board/smdk2440
2> /board/smdk2440 : mv smdk2410.c smdk2440.c
3> /board/smdk2440 : Makefile smdk2410.o smdk2440.o
4> 顶层Makefile
smdk2440_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2440 NULL s3c24x0
5> /include/configs: cp smdk2410.h smdk2440.h

编译:
make smdk2440_config
make

二、 支持sdram :
board/smdk2440/lowlevel.S
#define REFCNT 1113
==>
#define REFCNT 0x4f4

三、修改时钟
1> /board/smdk2440/smdk2440.c
目的:
FCLK=400MHz
FCLK:HCLK:PCLK =1:4:8
UPLL=48MHz,即UCLK=48MHz
修改:
..smdk2440/smdk2440.c

#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
#define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */

int board_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

clk_power->CLKDIVN = S3C2440_CLKDIV;

__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
:::"r1"
);
...
clk_power->LOCKTIME = 0xFFFFFFFF;
clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
delay (4000);
clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
delay (8000);
gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
}

2> 修改speed.c //cpu/arm920t/s3c24x0/
编译出错:
speed.c: In function `get_HCLK':
speed.c:107: error: structure has no member named `CAMDIVN'
speed.c: In function `get_PCLK':
speed.c:142: error: structure has no member named `CAMDIVN'
make[1]: *** [speed.o] 错误 1

原因: 2440时钟设置比2410多一些寄存器
解决:
在include/s3c24x0.h里面添加`CAMDIVN'即可
/**################################################################################################**/
四、支持NOR
include/configs/smdk2440.h
修改为:
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/

//注释掉下面两个类型的Nor Flash设置(CONFIG_AMD_LV400,CONFIG_AMD_LV800),因为不是我们所使用的型号
#if 0
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif

//add by fanlin for smdk2440 MX29LV160B
#define CONFIG_MX29LV160B 1

#ifdef CONFIG_MX29LV160B
#define CONFIG_MX29LV160B 1 //jz2440 Nor Flash
#define PHYS_FLASH_SIZE 0x200000 //2M
#define CFG_MAX_FLASH_SECT (35) //扇区数
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x80000) //0x80000为参数开始存放位置
#endif

添加id
>vi include/flash.h

第181行添加
//add by fanlin
#define MX29LV160B 0x22492249

在board/smdk2440/flash.c修改:
//add by fanlin
#define MAIN_SECT_SIZE 0x8000 // 定义为32k,主要扇区的大小

//#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
//#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))

屏蔽LV400/LV800后需要识别:flash.c
#elif defined(CONFIG_AMD_LV800)
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV800B & FLASH_TYPEMASK);
#elif defined(CONFIG_MX29LV160B) //add by fanlin
(AMD_MANUFACT & FLASH_VENDMASK) |
(MX29LV160B & FLASH_TYPEMASK);

由于我们是把norflash连接到了s3c2440的bank0上,因此norflash中的地址相对于s3c2440来说基址为0x00000000,即CFG_FLASH_BASE = 0。
而之所以又把norflash中的地址向左移一位(即乘以2),是因为我们是把s3c2440的ADDR1连接到了norflash的A0上的缘故。

由数据手册可知EN29LV160AB第0扇区大小为8K,第1、2为4K,第3为16K,后面31扇区为32K。前面4个扇区加起来刚好是主要扇区的大小 = 32K, 所以修改87行下如下

for (j = 0; j < flash_info[i].sector_count; j++) //主要修改几个数字
{
if (j <= 3)
{
/* 1st one is 8 KB */
if (j == 0)
{
flash_info[i].start[j] = flashbase + 0;
}

/* 2nd and 3rd are both 4 KB */
if ((j == 1) || (j == 2))
{
flash_info[i].start[j] = flashbase + 0x2000 + (j - 1) * 0x1000;
}

/* 4th 16 KB */
if (j == 3)
{
flash_info[i].start[j] = flashbase + 0x4000;
}
}
else
{
flash_info[i].start[j] = flashbase + (j - 3) * MAIN_SECT_SIZE;
}
}
size += flash_info[i].size;

修改flash_print_info,添加MX29LV160B相关信息如下:

switch (info->flash_id & FLASH_VENDMASK) {
case (AMD_MANUFACT & FLASH_VENDMASK):
printf ("AMD: ");
break;
case (MX_MANUFACT & FLASH_VENDMASK): //add by fanlin
printf ("MXIC: ");
break;
default:
printf ("Unknown Vendor ");
break;
}

switch (info->flash_id & FLASH_TYPEMASK) {
case (AMD_ID_LV400B & FLASH_TYPEMASK):
printf ("1x Amd29LV400BB (4Mbit)\n");
break;
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf ("1x Amd29LV800BB (8Mbit)\n");
break;
case (MX29LV160B & FLASH_TYPEMASK): //add by fanlin
printf ("1x MX29LV160B (16Mbit)\n");
break;
default:
printf ("Unknown Chip Type\n");
goto Done;
break;
}

修改int flash_erase (flash_info_t * info, int s_first, int s_last)
if ((info->flash_id & FLASH_VENDMASK) !=
//(AMD_MANUFACT & FLASH_VENDMASK)) {
(MX_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
}
至此,uboot关于Norflash已经移植好

以上,只是识别了nor,但是并不能启动内核
/*##############################################################################################*/
以上怀疑,nor并没能被正确识别,因为修改#define MX29LV160B 0x22492249对打印信息没影响
采用u-boot.2012.04.01移植方法:

在drivers里面添加jedec_flash.c,修改Makefile

1>在board/smdk2440/Makefile 里面去掉flash.o
2>在include/configs/smdk2440.h里面添加

#define CFG_FLASH_CFI 1
#define CFG_FLASH_CFI_DRIVER 1

在flash.h里面添加:
ypedef struct {
ulong size; /* total bank size in bytes */
ushort sector_count; /* number of erase units */
ulong flash_id; /* combined device & manufacturer code */
ulong start[CFG_MAX_FLASH_SECT]; /* physical sector start addresses */
uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */
#ifdef CFG_FLASH_CFI
uchar portwidth; /* the width of the port */
uchar chipwidth; /* the width of the chip */
ushort buffer_size; /* # of bytes in write buffer */
ulong erase_blk_tout; /* maximum block erase timeout */
ulong write_tout; /* maximum write timeout */
ulong buffer_write_tout; /* maximum buffer write timeout */
ushort vendor; /* the primary vendor id */
ushort cmd_reset; /* vendor specific reset command */
ushort interface; /* used for x8/x16 adjustments */
ushort legacy_unlock; /* support Intel legacy (un)locking */
//add by fanlin
uchar manufacturer_id; /* manufacturer id */
ushort device_id; /* device id */
ushort device_id2; /* extended device id */
ushort ext_addr; /* extended query table address */
ushort cfi_version; /* cfi version */
ushort cfi_offset; /* offset for cfi query */
ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
//end of fanlin
#endif

怎么样可以让nand里面识别出 nor flash ?
flash_init()里面有:
if (!flash_detect_legacy(cfi_flash_bank_addr(i), i)) //先使用flash_detect_legacy老版本来检测
//#ifdef CONFIG_FLASH_CFI_LEGACY使用这个宏来决定使用哪一个
flash_get_size(cfi_flash_bank_addr(i), i); //新方法

flash_detect_legacy里面调用
flash_read_jedec_ids(info);得到ID信息
jedec_flash_match //匹配ID信息
遍历jedec_table数组,找到对应芯片

我们使用的芯片是MX29LV160DB,但是uboot里面没有,而有相近的AM29LV040B,这是需要借助数据手册仿写一个

jedec_flash_match在jedec_flash.c里面,我把这个文件从u-boot-2012.04.01里面直接拿过来放在drivers/下
并修改Makefile

以上可以在nor里面启动内核,但是弄好nand后,在nand启动会出现如下内容:
DRAM: 64 MB
## Unknown FLASH on Bank 0 - Size = 0x00000000 = 0 MB
Flash: 0 kB
NAND: 256 MiB
*** Warning - bad CRC or NAND, using default environment

表示nor没有被识别:
查看“Flash: ”的位置发现:
DRAM: 打印信息在init_sequence --> display_dram_config
Flash: 打印信息在start_armboot --> display_flash_config
NAND: 打印信息在start_armboot -->puts ("NAND: ") -->nand_init

对于flash来说,其实现这里不是flash.c里面,因为我们使用的芯片不是lv400或者LV800
flash_init在cfi_flash.c里面

高版本uboot里面使用如下来识别cfi协议下的nor:
if (!flash_detect_legacy (BANK_BASE(i), i))
jedec_flash_match 匹配
flash_get_size (BANK_BASE(i), i);

因为:启动内核依赖#define CONFIG_BOOTCOMMAND "nboot 0x32000000 0 0 ; bootm 0x32000000"
这表明需要支持nand命令

/**################################################################################################**/
支持NAND 启动
首先增加nand命令 include/configs/smdk2440.h
#define CONFIG_COMMANDS \
((CONFIG_CMD_DFL | \
...
CFG_CMD_NAND | \

直接编译
error:
nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)
nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)
nand.c:35: error: storage size of `nand_info' isn't known
nand.c:37: error: storage size of `nand_chip' isn't known
nand.c:38: error: storage size of `base_address' isn't known
解决:
在配置文件smdk2440.h里面添加三个宏
#define CFG_NAND_BASE 0
#define CFG_MAX_NAND_DEVICE 1
#define NAND_MAX_CHIPS 1
只剩一个error:
..nand/nand.c:50: undefined reference to `board_nand_init'
解决:
在cpu/arm920t/s3c24x0/下建立新文件nand_flash.c实现board_nand_init函数

但是先定义结构体 在include/s3c24x0.h添加 S3C2440_NAND
/* for 2440 nand flash */
typedef struct{
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;

}S3C2440_NAND;

nand_flash.c内容如下:
/####################################################################################/start of nand_flash.c
/*
* Nand flash interface of s3c2410/s3c2440, by fanlin
* Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13
*/

#include <common.h>

#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <s3c2410.h>
#include <nand.h>

DECLARE_GLOBAL_DATA_PTR;

#define S3C2410_NFSTAT_READY (1<<0)
#define S3C2410_NFCONF_nFCE (1<<11)

#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2440_NFCONT_nFCE (1<<1)

/* select chip, for s3c2410 */
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

if (chip == -1) {
s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
} else {
s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
}
}

/* command and control functions, for s3c2410
*
* Note, these all use tglx's method of changing the IO_ADDR_W field
* to make the code simpler, and use the nand layer's code to issue the
* command and address sequences via the proper IO ports.
*
*/
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
struct nand_chip *chip = mtd->priv;

switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;

case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
break;

case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
break;

/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
break;
}
}

/* s3c2410_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2410_nand_devready(struct mtd_info *mtd)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}

/* select chip, for s3c2440 */
static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

if (chip == -1) {
s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
} else {
s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
}
}

/* command and control functions */
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
struct nand_chip *chip = mtd->priv;

switch (cmd) {
case NAND_CTL_SETNCE:
case NAND_CTL_CLRNCE:
printf("%s: called for NCE\n", __FUNCTION__);
break;

case NAND_CTL_SETCLE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
break;

case NAND_CTL_SETALE:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
break;

/* NAND_CTL_CLRCLE: */
/* NAND_CTL_CLRALE: */
default:
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
break;
}
}

/* s3c2440_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}

/*
* Nand flash hardware initialization:
* Set the timing, enable NAND flash controller
*/
static void s3c24x0_nand_inithw(void)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2

/* Set flash memory timing */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* Initialize ECC, enable chip select, NAND flash controller enable */
s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);

}

/*
* Called by drivers/nand/nand.c, initialize the interface of nand flash
*/
void board_nand_init(struct nand_chip *chip)
{
S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

s3c24x0_nand_inithw();

chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
chip->hwcontrol = s3c2440_nand_hwcontrol;
chip->dev_ready = s3c2440_nand_devready;
chip->select_chip = s3c2440_nand_select_chip;
chip->options = 0;

chip->eccmode = NAND_ECC_SOFT;
}

#endif

/####################################################################################/end of nand_flash.c

仿照include/s3c2410.h里面的S3C2410_GetBase_NAND函数定义S3C2440_GetBase_NAND函数
/* FOR 2440 */
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2410_NAND_BASE;
}

还得添加默认环境变量才可以nor flash启动内核

在smdk2440.h里面添加环境变量
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_CMDLINE_TAG 1

//#define CONFIG_BOOTCOMMAND "nboot 0x30000000 0 0 ; bootm 0x30000000"
#define CONFIG_BOOTCOMMAND "nand read.jffs2 0x30007FC0 0x60000 0x200000; bootm 0x30007FC0"

这样就可以启动内核了。
/**################################################################################################**/

支持mtdpart分区
搜索可知,mtdpart在cmd_jffs2.c里面定义

1.在smdk2440.h里面添加命令CFG_CMD_JFFS2

#define CONFIG_JFFS2_CMDLINE 1
#define CONFIG_JFFS2_NAND 1

#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \
"128k(params)," \
"2m(kernel)," \
"-(root)"

以上,不能发现mtdpart分区
cmd_jffs2里面do_jffs2_mtdparts函数开始修改为:
setenv("mtdids", (char *)mtdids_default);
setenv("mtdparts", (char *)mtdparts_default);
setenv("partition", NULL);

mtdparts_init();

if (argc == 2) {
if (strcmp(argv[1], "default") == 0) {
//setenv("mtdids", (char *)mtdids_default);
//setenv("mtdparts", (char *)mtdparts_default);
//setenv("partition", NULL);

//mtdparts_init();
...
100ask处理办法如下:
在main.c的main_loop函数里面添加:‘
#ifdef CONFIG_JFFS2_CMDLINE
extern int mtdparts_init(void);
if (!getenv("mtdparts"))
{
run_command("mtdparts default", 0);
}
else
{
mtdparts_init();
}
#endif

/**################################################################################################**/

输入print命令打印如下:
bootdelay=3
baudrate=115200
ipaddr=10.0.0.110
serverip=10.0.0.1
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial

配置网络ping主机
CS8900 Ethernet chip not found?!

支持dm9000

在driver下,有网卡驱动DM9000x.c和 DM9000x.h
DM9000接在BANK4,位宽16

在include/configs/smdk2440.h中设置网卡基地址:
在56行处,将CS8900的定义改成:

#if 1
#if 0
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
#endif

#if !defined(CONFIG_DRIVER_CS8900)
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_USE_16BIT 1
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO 0x20000000
#define DM9000_DATA 0x20000004
#endif
#endif

编译可生成支持网卡的uboot
如果显示:
# ping 10.140.1.250
MAC: 08:08:08:08:008:08
could not establish link

将100ask的dm9000x.c替换当前的文件,说明dm9000x.c里面有问题,日后再研究

烧录后显示:
SMDK2440 # ping 192.168.1.17
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:0c:29:45:c4:c5
could not establish link
host 192.168.1.17 is alive

表示ping通了。

/**################################################################################################**/
设置环境变量的存储地址:

原来的环境变量的配置:
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE

上面说过不要用save命令保存环境变量设置,目的是防止flash被破坏:
查看save命令帮助信息,知道saveenv,搜索saveenv
或者在SI里面搜索可得,在common目录下看Makefile,知道依赖上面宏
Env_nand.c (common):int saveenv(void)

makefile里面有:
COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
可知需要CONFIG_ENV_IS_IN_NAND

不光如此,还需要知道起始地址和大小
打开env_nand.c,里面有CONFIG_ENV_SIZE和CONFIG_ENV_OFFSET

上面的还不够,还需要擦除长度
nand_erase_options.length = CONFIG_ENV_RANGE;

即需要定义CONFIG_ENV_RANGE,设为CONFIG_ENV_SIZE

分区:
device nand0 <nandflash0>, # parts = 4
#: name size offset mask_flags
0: bootloader 0x00040000 0x00000000 0
1: params 0x00020000 0x00040000 0
2: kernel 0x00200000 0x00060000 0
3: root 0x0fda0000 0x00260000 0

综上所知设置为:
//#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0x40000
#define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */

bootcmd=nand read.jffs2 30000000 kernel; bootm 30000000

/***************************************分界线********************************************/
支持yaffs2文件的烧写

tftp 30000000 fs_mini_mdev.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 0x00260000 xx

set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

烧写ok

烧写yaffs
tftp 30000000 fs_mini_mdev.yaffs2 //fs_qtopia.yaffs2
nand erase.part root
nand write.yaffs 30000000 260000 2f76b40

出现错误:
nand_write_ecc: Attempt to write not page aligned data
0 bytes written: ERROR

措施:

在cmd_nand.c里面U_BOOT_CMD(nand, 5, 1, do_nand,
添加
"nand read.yaffs addr off size - read the `size' byte yaffs image starting\n"
" at offset `off' to memory address `addr'\n"
"nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"
" at offset `off' from memory address `addr'\n"

do_nand函数里面:
else if ( s != NULL && !strcmp(s, ".yaffs")){
if (read) {
/* read */
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
opts.readoob = 1;
opts.quiet = quiet;
ret = nand_read_opts(nand, &opts);
} else {
/* write */
nand_write_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer = (u_char*) addr;
opts.length = size;
opts.offset = off;
/* opts.forceyaffs = 1; */ 注意这里
opts.noecc = 1;
opts.writeoob = 1;
opts.blockalign = 1;
opts.quiet = quiet;
opts.skipfirstblk = 1; 新添加的
ret = nand_write_opts(nand, &opts);
}
在nand.h里面加上opts.skipfirstblk以及其实现

struct nand_write_options {
u_char *buffer; /* memory block containing image to write */
ulong length; /* number of bytes to write */
ulong offset; /* start address in NAND */
int quiet; /* don't display progress messages */
int autoplace; /* if true use auto oob layout */
int forcejffs2; /* force jffs2 oob layout */
int forceyaffs; /* force yaffs oob layout */
int noecc; /* write without ecc */
int writeoob; /* image contains oob data */
int pad; /* pad to page size */
int blockalign; /* 1|2|4 set multiple of eraseblocks
* to align to */
int skipfirstblk; //这两项添加的
int nocheckbadblk;

};

修改nand_write_opts函数,对int skipfirstblk的支持,文件在nand_util.c的nand_write_opts

int skipfirstblk = opts->skipfirstblk;

/* skip the first good block when wirte yaffs image, by www.100ask.net */
if (skipfirstblk) {
mtdoffset += erasesize_blockalign;
skipfirstblk = 0;
continue;
}

上面由于不用ecc,会出现很多警告信息如:
Writing data without ECC to NAND-FLASH is not recommended\n
可以在nand_base.c里面的nand_write_page函数里面屏蔽掉:
case NAND_ECC_NONE:
//printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
this->write_buf(mtd, this->data_poi, mtd->oobblock);

补丁制作过程:
1.make distclean
2.rm u-boot.lds
3.cd ..
4.rm u-boot-2012.xx u-boot-2012.xx_ok
5.解压原来下载的源码tar xjf u-boot-2012.xx.tar
6.制作补丁:
diff -urN u-boot-2012.xx u-boot-2012.xx_ok > u-boot-2012.xx.patch

补丁制作ok。