基於mx27ads 的yaffs 檔案系統釋疑

2021-08-22 14:25:35 字數 3873 閱讀 4057

mx27ads bsp核心採用2.6.19

, 選擇檔案系統中的yaffs2

file systems ---> miscellaneous filesystems ---> <*> yaffs2 file system support

建立測試的yaffs image

mkdir userfs

echo test > userfs/test

mkyaffsimage userfs userfs.yaffs

寫入nand flash

nandwrite –a –o /dev/mtd/8 userfs.yaffs

掛載yaffs mtd

mount –t yaffs /dev/mtdblock/8 /mnt/rwfs

發現mount報錯, 只有乙個lost+found目錄, 其餘空空如也. 看樣子只好分析yaffs和nand flash**了.

mx27的使用的是8bit 512bytes+16bytes oob/page 的128m

nand flash, 分析yaffs與nand flash驅動**, 發現yaffs中呼叫yaffs_mtdif.c中的nandmtd_writechunktonand函式將它的chunk寫入flash,包含乙個512位元組的資料與yaffs_spare結構, 512位元組資料對應nand flash 一page, 所以不需要關心他的512位元組資料區; yaffs_spare結構,在yaffs_guts.h中定義的

typedef struct yaffs_spare;

正好是16位元組, 那就是使用這16位元組作為oob. 其中ecc1與ecc2是用來計算ecc的, 只有使用yaffs自身的ecc時才用到, 我們這裡使用mtd的硬體ecc, 可以忽略不計, 省下了yaffs用來存放檔案系統相關的資訊(yaffs_tags)8個bytes. 而mx27 nand flash 其oob定義如下:

static struct nand_ecclayout nand_hw_eccoob_8 = ,

.oobfree = , }

};oobfree有兩塊, , 總共10個位元組. 需要將這8個位元組儲存到oob區中, 就需要乙個轉換. 繼續分析yaffs_mtdif.c時,發現2.6.19核心在yaffs寫入oob時先使用translate_spare2oob將yaffs_spare轉換為乙個8bytes資料塊,然後通過mtd->write_oob使用mtd_oob_auto方式寫入oob資料;

…#if (linux_version_code > kernel_version(2,6,17))

__u8 spareasbytes[8]; /* oob */

//只有資料

if (data && !spare)

retval = mtd->write(mtd, addr, dev->ndatabytesperchunk,

&dummy, data);

else if (spare)

else

ops.len = data ? dev->ndatabytesperchunk : ops.ooblen;

ops.datbuf = (u8 *)data;

ops.ooboffs = 0;

ops.oobbuf = spareasbytes;

retval = mtd->write_oob(mtd, addr, &ops);

}#endif

…繼續深入分析, 發現mtd-write_oob實際上是呼叫的是nand_do_write_ops或nand_do_write_oob(都在driver/mtd/nand/nand_base.c), 在這兩個函式中在處理oob資料時都呼叫了同乙個函式nand_fill_oob:

static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,

struct mtd_oob_ops *ops)

boffs = free->offset + woffs;

bytes = min_t(size_t, len,

(free->length - woffs));

woffs = 0;

} else

memcpy(chip->oob_poi + boffs, oob, bytes);

oob += bytes;

}return oob;

}default:

bug();

}return null;

}可以看出nand_fill­_oob使用了2種方式來組織oob的處理方式: mtd_oob_place與mtd_oob_raw為一種, 直接將oob資料複製到要寫入oob的資料快取chip->oob_poi; mtd_oob_auto講oob資料複製到要寫入oob的資料快取oobfree位置上. 這就是mtd_oob_raw與mtd_oob_auto的最終解釋了.

再來看mkyaffsimage的**:

static int write_chunk(__u8 *data, __u32 objid, __u32 chunkid, __u32 nbytes)

yaffs_calctagsecc(&t);

yaffs_loadtagsintospare(&s,&t);

yaffs_calcecc(data,&s);

npages++;

return write(outfile,&s,sizeof(yaffs_spare)); }

他在512位元組之後是包含了16位元組yaffs_spare的,這個16位元組的yaffs_spare就是他的oob結構. 但是這個16位元組並沒有通過translate_spare2oob轉換, 而是直接寫入image中了.

再看通過nandwrite -a -o 寫入mtd時的**

if (!noecc)

} else

}可見nandwrite在寫入oob時是也是通過mtd_nandecc_autoplace(等同mtd_oob_auto)方式寫入的.

比較一下yaffs流程與mkyaffsimage流程:

yaffs流程是通過translate_spare2oob將8bytes的yaffs_tags轉為8bytes資料塊,然後通過write_oob將這8bytes寫入到oob的oobfree塊區; 讀出來的時候反過來translate_oob2spare, 就可以還原成yaffs_tags; 而mkyaffsimage建立yaffs image時卻是直接將yaffs_spare寫入檔案, 通過nandwrite -a -o 寫入mtd時, 直接使用這塊yaffs_spare作為oob資料寫入, 雖然使用方式也是mtd_oob_auto; 這就造成yaffs讀取chunk時無法讀取正確的yaffs_spare資料了;

由此可見只要在mkyaffsimage寫入yaffs_spare時, 只要將寫入的資料轉換為yaffs中寫入flash之前一致的資料即可.

以下是修改過的write_chunk

static int write_chunk(__u8 *data, __u32 objid, __u32 chunkid, __u32 nbytes)

yaffs_calctagsecc(&t);

yaffs_loadtagsintospare(&s,&t);

yaffs_calcecc(data,&s);

npages++;

#if 0

return write(outfile,&s,sizeof(yaffs_spare));

#else

memset(oobdata,0xff,16);

translate_spare2oob( &s, oobdata )

//因為採用的是硬體ecc, 這裡忽略了yaffs自身的ecc

return write(outfile, oobdata, 16);

#endif

}

基於linux 3 10的yaffs2移植

git clone git cd yaffs2 patch ker.sh c m linux3.10 mini24402.然後在linux的源 fs中多了乙個yaffs2的資料夾,到此yaffs2檔案系統就已經新增到linux3.10中了。在linux核心源 根目錄執行 make menuconfi...

基於ADS1 2下的ARM應用開發

1.巨集定義中volatile uint8 uint8等效於unsigned char,而volatile關鍵字主要作用是針對變數可能在編譯器控制之外被修改的情況,強制讓編譯器放棄對這個變數的優化。volatile 因為c編譯器的優化作用以及作業系統的cache等的影響,某些變數的值在記憶體中和暫存...

基於STM32的ADS1115使用例程

ads1232之stm32程式 stm32測試高精度adc篇 一 cherrymcu的部落格 csdn部落格 ads1232 基於ad7190的精密電子稱 4.8khz超低聲24位 adc,內建pga deming 0的部落格 csdn部落格 ad7190 cs5532 基於stm32的ads111...