u-boot默认不支持yaffs2文件系统镜像的烧写,现在加入烧写yaffs2文件系统的命令,并修改NandFlash程序中写操作的处理方式,移植的步骤如下:
(1)在smdk2440.h中加入支持yaffs2的配置,修改的代码如下:
- #define ENABLE_CMD_LOADB_X 1
- #define ENABLE_CMD_NAND_YAFFS 1
- #define ENABLE_CMD_NAND_YAFFS_SKIPFB
(2)在common/cmd_nand.c中增加烧写yaffs2的命令支持,先是修改do_nand函数,修改的代码如下:
- s = strchr(cmd, '.');
- if (!s || !strcmp(s, ".jffs2") ||
- !strcmp(s, ".e") || !strcmp(s, ".i")) {
- if (read)
- ret = nand_read_skip_bad(nand, off, &size,
- (u_char *)addr);
- else
- ret = nand_write_skip_bad(nand, off, &size,
- (u_char *)addr);
- #if defined(ENABLE_CMD_NAND_YAFFS)
- }else if ( s != NULL &&
- (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))){
- if(read) {
- printf("nand read.yaffs[1] is not provide temporarily!");
- } else {
- nand->rw_oob = 1;
- #if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
- nand->skipfirstblk = 1;
- #else
- nand->skipfirstblk = 0;
- #endif
- ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr);
- #if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
- nand->skipfirstblk = 0;
- #endif
- nand->rw_oob = 0;
- }
- #endif
- } else if (!strcmp(s, ".oob")) {
- /* out-of-band data */
- mtd_oob_ops_t ops = {
- .oobbuf = (u8 *)addr,
- .ooblen = size,
- .mode = MTD_OOB_RAW
- };
接着在U_BOOT_CMD处修改代码如下:
- U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
- "NAND sub-system",
- "info - show available NAND devices\n"
- "nand device [dev] - show or set current device\n"
- "nand read - addr off|partition size\n"
- "nand write - addr off|partition size\n"
- " read/write 'size' bytes starting at offset 'off'\n"
- " to/from memory address 'addr', skipping bad blocks.\n"
- "nand erase [clean] [off size] - erase 'size' bytes from\n"
- " offset 'off' (entire device if not specified)\n"
- #if defined(ENABLE_CMD_NAND_YAFFS)
- "nand read[.yaffs[1]] is not provide temporarily!\n"
- "nand write[.yaffs[1]] addr off size - write the `size' byte yaffs image starting\n"
- " at offset `off' from memory address `addr' (.yaffs1 for 512+16 NAND)\n"
- #endif
- "nand bad - show bad blocks\n"
- "nand dump[.oob] off - dump page\n"
- "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
- "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
- "nand biterr off - make a bit error at offset (UNSAFE)"
- #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
- "\n"
- "nand lock [tight] [status]\n"
- " bring nand to lock state or display locked pages\n"
- "nand unlock [offset] [size] - unlock section"
- #endif
- );
(3)修改include/linux/mtd/目录下的mtd.h文件,在mtd_info结构体中增加两个变量,这两个变量要在后面修改NandFlash驱动时使用,修改的代码如下:
- u_int32_t writesize;
- u_char rw_oob;
- u_char skipfirstblk;
- u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
- u_int32_t oobavail; /* Available OOB bytes per block */
接着修改结构体erase_info结构体中的uint64_t addr成员,修改的代码如下:
- struct erase_info {
- struct mtd_info *mtd;
- u_long addr; //uint64_t addr
- uint64_t len;
- uint64_t fail_addr;
- u_long time;
- u_long retries;
- u_int dev;
- u_int cell;
- void (*callback) (struct erase_info *self);
- u_long priv;
- u_char state;
- struct erase_info *next;
- };
(4)修改drivers/mtd/nand/目录下nand_util.c文件中的nand_write_skip_bad函数,修改的代码如下:
- int nand_write_skip_bad(nand_info_t *nand, __kernel_ino_t offset, size_t *length,
- u_char *buffer) /* zjw modify 20121021 */
- {
- int rval;
- size_t left_to_write = *length;
- size_t len_incl_bad;
- u_char *p_buffer = buffer;
- #if defined(ENABLE_CMD_NAND_YAFFS)
-
- if(nand->rw_oob==1) {
- size_t oobsize = nand->oobsize;
- size_t datasize = nand->writesize;
- int datapages = 0;
-
- //if (((*length)%(nand->oobsize+nand->writesize)) != 0) {
- //printf ("Attempt to write error length data!\n");
- //return -EINVAL;
- //}
- datapages = *length/(datasize+oobsize);
- *length = datapages*datasize;
- left_to_write = *length;
- //nand->skipfirstblock=1;
- }
- #endif
- /* Reject writes, which are not page aligned */
- if ((offset & (nand->writesize - 1)) != 0 ||
- (*length & (nand->writesize - 1)) != 0) {
- printf ("Attempt to write non page aligned data\n");
- return -EINVAL;
- }
- len_incl_bad = get_len_incl_bad (nand, offset, *length);
- if ((offset + len_incl_bad) > nand->size) {
- printf ("Attempt to write outside the flash area\n");
- return -EINVAL;
- }
- #if !defined(ENABLE_CMD_NAND_YAFFS)
- if (len_incl_bad == *length) {
- rval = nand_write (nand, offset, length, buffer);
- if (rval != 0)
- printf ("NAND write to offset %llx failed %d\n",
- offset, rval);
- return rval;
- }
- #endif
- while (left_to_write > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
- size_t write_size;
- WATCHDOG_RESET ();
- if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
- printf ("Skip bad block 0x%08lx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
- #if defined(ENABLE_CMD_NAND_YAFFS)
- if(nand->skipfirstblk==1) {
- nand->skipfirstblk=0;
- printf ("Skip the first good block %08lx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
- #endif
- if (left_to_write < (nand->erasesize - block_offset))
- write_size = left_to_write;
- else
- write_size = nand->erasesize - block_offset;
-
- printf("\rWriting at 0x%08lx -- ",offset); // zjw add 20121021
- rval = nand_write (nand, offset, &write_size, p_buffer);
- if (rval != 0) {
- printf ("NAND write to offset %08lx failed %d\n",
- offset, rval);
- *length -= left_to_write;
- return rval;
- }
- left_to_write -= write_size;
- printf("%d%% is complete.",100-(left_to_write/(*length/100)));
- offset += write_size;
- #if defined(ENABLE_CMD_NAND_YAFFS)
- if(nand->rw_oob==1) {
- p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
- } else {
- p_buffer += write_size;
- }
- #else
- p_buffer += write_size;
- #endif
- }
- return 0;
- }
(5)修改drivers/mtd/nand/目录下的nand_base.c文件,先修改nand_do_write_ops函数,修改的代码如下:
- writelen -= bytes;
- if (!writelen)
- break;
- column = 0;
- #if defined(ENABLE_CMD_NAND_YAFFS)
- if(mtd->rw_oob == 1) {
- oob = oob + bytes;
- buf = buf + ops->ooblen;
- }
- #endif
- buf += bytes;
- realpage++;
接着修改nand_write函数,修改的代码如下:
- static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const uint8_t *buf)
- {
- struct nand_chip *chip = mtd->priv;
- int ret;
- #if defined(ENABLE_CMD_NAND_YAFFS)
- int oldopsmode = 0;
- if(mtd->rw_oob != 1) {
- chip->ops.oobbuf = NULL;
- } else {
- chip->ops.oobbuf = (uint8_t *)(buf + mtd->writesize);
- chip->ops.ooblen = mtd->oobsize;
- chip->ops.ooboffs = 0;
- oldopsmode = chip->ops.mode;
- chip->ops.mode = MTD_OOB_RAW;
- }
- #else
- chip->ops.oobbuf = NULL;
- #endif
- #if 0
- #if defined(ENABLE_CMD_NAND_YAFFS)
- int oldopsmode = 0;
- if(mtd->rw_oob == 1){
- size_t oobsize = mtd->oobsize;
- size_t datasize = mtd->writesize;
- int i = 0;
- uint8_t oobtemp[oobsize];
- int datapages = 0;
-
- datapages = len/(datasize);
- for(i=0;i<(datapages);i++) {
- memcpy((void *)oobtemp,
- (void *)(buf+datasize*(i+1)),
- oobsize);
- memmove((void *)(buf+datasize*(i+1)),
- (void *)(buf+datasize*(i+1)+oobsize),
- (datapages-(i+1))*(datasize)+(datapages-1)*oobsize);
- memcpy((void *)(buf+(datapages)*(datasize+oobsize)-oobsize),
- (void *)(oobtemp),
- oobsize);
- }
- }
- #endif
- #endif
- /* Do not allow reads past end of device */
- if ((to + len) > mtd->size)
- return -EINVAL;
- if (!len)
- return 0;
- nand_get_device(chip, mtd, FL_WRITING);
- chip->ops.len = len;
- chip->ops.datbuf = (uint8_t *)buf;
- //chip->ops.oobbuf = NULL; // zjw del 20121021
- #if 0
- #if defined(ENABLE_CMD_NAND_YAFFS)
- if(mtd->rw_oob!=1) {
- chip->ops.oobbuf = NULL;
- } else {
- chip->ops.oobbuf = (uint8_t *)(buf+len);
- chip->ops.ooblen = mtd->oobsize;
- oldopsmode = chip->ops.mode;
- chip->ops.mode = MTD_OOB_RAW;
- }
- #else
- chip->ops.oobbuf = NULL;
- #endif
- #endif
- ret = nand_do_write_ops(mtd, to, &chip->ops);
- *retlen = chip->ops.retlen;
- nand_release_device(mtd);
- #if defined(ENABLE_CMD_NAND_YAFFS)
- chip->ops.mode = oldopsmode;
- #endif
- return ret;
- }
(6)修改include/nand.h文件中关于nand_write_skip_bad函数的声明,修改的代码如下:
- int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer);
- int nand_write_skip_bad(nand_info_t *nand, __kernel_ino_t offset, size_t *length, u_char *buffer);
- int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
(7)在nand_util.c中修改nand_erase_opts函数,修改后的代码如下:
- if (!opts->scrub && bbtest) {
- int ret = meminfo->block_isbad(meminfo, erase.addr);
- if (ret > 0) {
- if (!opts->quiet)
- printf("\rSkipping bad block at "
- "0x%08lx " /* zjw modify 20121021 */
- " \n",
- erase.addr);
- continue;
- } else if (ret < 0) {
- printf("\n%s: MTD get bad block failed: %d\n",
- mtd_device,
- ret);
- return -1;
- }
- }
if (percent != percent_complete) {
percent_complete = percent;
printf("\rErasing at 0x%08lx -- %3d%% complete.", erase.addr, percent);
if (opts->jffs2 && result == 0)
printf(" Cleanmarker written at 0x%08lx.", erase.addr);
}
最后重新编译u-boot,下载到NandFlash中运行,u-boot此时就可以支持烧写yaffs2文件系统镜像了。
阅读(1181) | 评论(0) | 转发(0) |