這里用到y(tǒng)affs2主要是它的寫(xiě)功能,所以只添加yaffs2關(guān)于寫(xiě)部分的代碼,參考了網(wǎng)上別人的代碼。 在include/configs/TE2440II.h 中添加 #define CONFIG_MTD_NAND_YAFFS21//定義一個(gè)管理對(duì)Yaffs2支持的宏 //開(kāi)啟Nand Flash默認(rèn)分區(qū),注意此處的分區(qū)要和你的內(nèi)核中的分區(qū)保持一致 #define MTDIDS_DEFAULT"nand0=nandflash0" #define MTDPARTS_DEFAULT"mtdparts=nandflash0:192k(bootloader),"\ "64k(params),"\ "2m(kernel),"\ "-(root)" 添加命令: #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的寫(xiě)命令,因?yàn)槲覀冎挥胾-boot下載(即寫(xiě))功能,所以我們沒(méi)有添加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 ); 接著,在該文件中對(duì)nand操作的do_nand函數(shù)中添加yaffs2對(duì)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相關(guān)操作,注意該處又關(guān)聯(lián)到nand_write_skip_bad函數(shù) #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; } 在include/linux/mtd/mtd.h頭文件的mtd_info結(jié)構(gòu)體中添加上面用到rw_oob和skipfirstblk數(shù)據(jù)成員,如下: #gedit include/linux/mtd/mtd.h//在mtd_info結(jié)構(gòu)體中添加 #if defined(CONFIG_MTD_NAND_YAFFS2) u_char rw_oob; u_char skipfirstblk; #endif 在第二步關(guān)聯(lián)的nand_write_skip_bad函數(shù)中添加對(duì)Nand OOB的相關(guān)操作,如下: #gedit drivers/mtd/nand/nand_util.c//在nand_write_skip_bad函數(shù)中添加 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; } 在第四步nand_write_skip_bad函數(shù)中我們看到又對(duì)nand_write函數(shù)進(jìn)行了訪問(wèn),所以這一步是到nand_write函數(shù)中添加對(duì)yaffs2的支持,如下: #gedit drivers/mtd/nand/nand_base.c//在nand_write函數(shù)中添加 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(CONFIG_MTD_NAND_YAFFS2)//add yaffs2 file system support int oldopsmode = 0; if(mtd->rw_oob==1) { int i = 0; int datapages = 0; size_t oobsize = mtd->oobsize; size_t datasize = mtd->writesize; uint8_t oobtemp[oobsize]; 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 /* 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; #if defined(CONFIG_MTD_NAND_YAFFS2)//add yaffs2 file system support 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 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; #endif return ret; } OK,對(duì)yaffs2支持的代碼已修改完畢,重新編譯u-boot并下載到nand中,啟動(dòng)開(kāi)發(fā)板,在u-boot的命令行輸入:nand help查看nand的命令,可以看到多了一個(gè)nand write[.yaffs2]的命令,這個(gè)就是用來(lái)下載yaffs2文件系統(tǒng)到nand中的命令了。 使用nand write[.yaffs2]命令把事前制作好的yaffs2文件系統(tǒng)下載到Nand Flash中,下載操作步驟和效果圖如下: tftp 0x30000000 root-2.6.30.4.bin//用tftp將yaffs2文件系統(tǒng)下載到內(nèi)存的0x30000000位置 nand erase 0x800000 0x3c00000//擦除Nand的文件系統(tǒng)分區(qū) nand write.yaffs2 0x30000000 0x800000 0x3c00000//將內(nèi)存中的yaffs2文件系統(tǒng)寫(xiě)入Nand的文件系統(tǒng)分區(qū),注意這里的0x658170是yaffs2文件系統(tǒng)的實(shí)際大小(可以在tftp傳送完后可以看到),要寫(xiě)正確,否則會(huì)形成假壞塊。 李萬(wàn)鵬 |