uboot.2015.07移植之裁剪uboot以及驱动yaffs(9)

时间:2021-02-06 16:31:10

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 基本移植完毕