1.移植u-boot-2015.07之修改程序对 u-boot 进行裁剪
- 在uboot的根文件夹下面 grep “CONFIG_ENV_IS_IN_FLASH” * -nR
得到在 common/Makefile 里面有以下语句
COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o 查看 env_nand.c 的 saveenv 函数里面,知道有 CONFIG_ENV_RANGE、CONFIG_ENV_RANGE、CONFIG_ENV_OFFSET 宏定义需要自行设置,以及要指定 CONFIG_ENV_IS_IN_NAND,这样才会 save 环境变量到 nand flash 里面
- 在 smdk2440.h 里面加上下面的宏定义
/* nand flash environment config */
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x40000
#define CONFIG_ENV_SIZE 0x20000 /* 1 sector = 128 kB */
/* boot config */
#define CONFIG_BOOTCOMMAND "nand read 0x30000000 0x60000 0x200000; bootm 30000000" //倒计时完成之后会执行的代码
#define CONFIG_BOOTARGS "console=ttySAC0,115200 " \ //要传给内核的参数
"root=/dev/mtdblock3 " \
"rootfstype=jffs2"
/* add mtdparts commond */
#define CONFIG_MTD_DEVICE
#define CONFIG_CMD_MTDPARTS
#define MTDIDS_DEFAULT "nand0=s3c-nand" //nand 后面必须跟一个阿拉伯数字,此处设置为 nand0
#define MTDPARTS_DEFAULT "mtdparts=s3c-nand:256k(bootloader)ro"\
",128k@0x40000(params)ro"\
",2m@0x60000(kernel)ro"\
",-(rootfs)ro"
关于 MTDIDS_DEFAULT 必须设置 nand0 的原因是在 cmd_mtdparts.c 中的 mtd_id_parse 函数中有 isdigit 来判断其参数是否为阿拉伯数字 0-9,也就是 nand 后面的0,如果不是的话会打印出错误,所以一定要加上去。关于mtdparts的格式参照 help mtdparts 给出的介绍
- 在 cmd_mtdparts.c 的 do_mtdparts 的以下代码段前面加上
/* make sure we are in sync with env variables */
if (mtdparts_init() != 0)
return 1;
//上面代码段前面加上下面的代码(不用每次都要手动执行 mtdparts default)
if(!getenv("mtdparts"))
{
setenv("mtdids", (char *)mtdids_default);
setenv("mtdparts", (char *)mtdparts_default);
setenv("partition", NULL);
}
- 在 sdmk2400.h 里面注释掉不用的命令,都是 CONFIG_CMD 开头的宏定义,不用的一律注释掉,要注意宏定义之间的依赖,这个根据编译的错误信息就可以找得到
2.移植u-boot-2015.07之修改程序使 nand 支持 yaffs 文件系统的烧写
由于此版本的 uboot 并没有在代码中支持 yaffs 文件系统的烧写,所以我们需要手动去添加代码(对比 uboot-2012 版的)
- 在 common/amd_nand.c 的 do_nand 函数里面添加 uboot-2012 中的相关代码并且进行修改
#ifdef CONFIG_CMD_NAND_YAFFS
} else if (!strcmp(s, ".yaffs")) {
if (read) {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
}
/* 下面的函数调用要进行修改,因为 uboot-2015-07 中此函数参数发生了变化 */
//ret = nand_write_skip_bad(nand, off, &rwsize,
// (u_char *)addr, WITH_YAFFS_OOB);
ret = nand_write_skip_bad(nand, off, &rwsize, NULL
maxsize, (u_char *)addr, WITH_YAFFS_OOB);
#endif
- 在 nand_help_text[] 数组里面添加如下说明(帮助信息)
#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
- 在 include/nand.h 中添加宏定义
#define WITH_YAFFS_OOB (1 << 0)
- 在 drivers/mtd/nand/nand_util.c 中的 nand_write_skip_bad 函数中分别添加以下程序块
//前面还有一个 if 判断,我们不管它,在下面添加
#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; //这里本来就有,不过我们要用花括号括起来
}
#ifdef CONFIG_CMD_NAND_YAFFS
if (flags & WITH_YAFFS_OOB) {
int page, pages;
size_t pagesize = nand->writesize;
size_t pagesize_oob = pagesize + nand->oobsize;
struct mtd_oob_ops ops;
ops.len = pagesize;
ops.ooblen = nand->oobsize;
//此处要修改为 MTD_OOB_RAW,表明 OOB 数据在要写的数据包里
//ops.mode = MTD_OOB_AUTO;
ops.mode = MTD_OOB_RAW;
ops.ooboffs = 0;
pages = write_size / pagesize_oob;
for (page = 0; page < pages; page++) {
WATCHDOG_RESET();
ops.datbuf = p_buffer;
ops.oobbuf = ops.datbuf + pagesize;
/* nand->write_oob 要修改,此版本没有 write_oob 成员,并且 if 判断也要修改 */
//rval = nand->write_oob(nand, offset, &ops);
//if (!rval)
// break;
rval = nand->_write_oob(nand, offset, &ops);
if (rval)
break;
offset += pagesize;
p_buffer += pagesize_oob;
}
}
else
#endif
{ //照例添加括号
truncated_write_size = write_size;
#ifdef CONFIG_CMD_NAND_TRIMFFS
if (flags & WITH_DROP_FFS)
truncated_write_size = drop_ffs(nand, p_buffer,
&write_size);
#endif
rval = nand_write(nand, offset, &truncated_write_size,
p_buffer);
offset += write_size;
p_buffer += write_size;
}
- 在 include/linux/mtd/mtd.h 里面添加如下的枚举类型
/*
* oob operation modes
*
* MTD_OOB_PLACE: oob data are placed at the given offset
* MTD_OOB_AUTO: oob data are automatically placed at the free areas
* which are defined by the ecclayout
* MTD_OOB_RAW: mode to read raw data+oob in one chunk. The oob data
* is inserted into the data. Thats a raw image of the
* flash contents.
*/
typedef enum {
MTD_OOB_PLACE,
MTD_OOB_AUTO,
MTD_OOB_RAW,
} mtd_oob_mode_t;
到这里 yaffs 文件的烧写就没问题了,uboot 基本移植完毕