分类: 嵌入式
2010-08-10 09:02:26
嵌入式学习入门 http://blog.chinaunix.net/u3/117680/showart.php?id=2300212
Yaffs页结构说明 |
#gedit include/configs/my2440.h //添加到文件末尾即可 |
#define CONFIG_MTD_NAND_YAFFS2 1 //定义一个管理对Yaffs2支持的宏 //开启Nand Flash默认分区,注意此处的分区要和你的内核中的分区保持一致 |
②、在原来对Nand操作的命令集列表中添加Yaffs2对Nand的写命令,如下:
#gedit common/cmd_nand.c //在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" //注意:这里只添加了yaffs2的写命令,因为我们只用u-boot下载(即写)功能,所以我们没有添加yaffs2读的命令
#if defined(CONFIG_MTD_NAND_YAFFS2) "nand write[.yaffs2] - addr off|partition size - write `size' byte yaffs image\n" " starting at offset off' from memory address addr' (.yaffs2 for 512+16 NAND)\n" #endif "nand erase [clean] [off size] - erase 'size' bytes from\n" " offset 'off' (entire device if not specified)\n" "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 ); |
接着,在该文件中对nand操作的do_nand函数中添加yaffs2对nand的操作,如下:
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0)
{ int read; if (argc < 4)
goto usage; addr = (ulong)simple_strtoul(argv[2], NULL, 16);
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
printf("\nNAND %s: ", read ? "read" : "write"); if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0) return 1; 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); } //添加yaffs2相关操作,注意该处又关联到nand_write_skip_bad函数
#if defined(CONFIG_MTD_NAND_YAFFS2)
else if (s != NULL && (!strcmp(s, ".yaffs2"))) { nand->rw_oob = 1; nand->skipfirstblk = 1; ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr); nand->skipfirstblk = 0; 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 }; if (read)
ret = nand->read_oob(nand, off, &ops); else ret = nand->write_oob(nand, off, &ops); } else { printf("Unknown nand command suffix '%s'.\n", s); return 1; } printf(" %zu bytes %s: %s\n", size, read ? "read" : "written", ret ? "ERROR" : "OK");
return ret == 0 ? 0 : 1; } |
#gedit include/linux/mtd/mtd.h //在mtd_info结构体中添加 |
#if defined(CONFIG_MTD_NAND_YAFFS2) |
#gedit drivers/mtd/nand/nand_util.c //在nand_write_skip_bad函数中添加 |
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer)
{ int rval; size_t left_to_write = *length; size_t len_incl_bad; u_char *p_buffer = buffer; #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
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; } #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(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
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%08llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; } #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
if(nand->skipfirstblk==1) { nand->skipfirstblk=0; printf ("Skip the first good block %llx\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%llx -- ",offset); //add yaffs2 file system support
rval = nand_write (nand, offset, &write_size, p_buffer); if (rval != 0) { printf ("NAND write to offset %llx 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(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
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; } |
#gedit drivers/mtd/nand/nand_base.c //在nand_write函数中添加 |
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const uint8_t *buf) #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support int oldopsmode = 0; if(mtd->rw_oob==1) size_t oobsize = mtd->oobsize; uint8_t oobtemp[oobsize]; for(i = 0; i < (datapages); i++) /* Do not allow reads past end of device */ nand_get_device(chip, mtd, FL_WRITING); chip->ops.len = len; #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if(mtd->rw_oob!=1) ret = nand_do_write_ops(mtd, to, &chip->ops); *retlen = chip->ops.retlen; nand_release_device(mtd); #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support chip->ops.mode = oldopsmode; return ret; |