本來(lái)FATFS系統(tǒng)有大量的資料可以參考,移植到STM32中有成熟的源碼,但是還是想研究一下官網(wǎng)的文檔介紹惜傲。
官網(wǎng)的鏈接如下FATFS APPLICATION NOTE
Performance Effective File Access
先理解一個(gè)概念volume,一個(gè)卷,也就是我說(shuō)的一個(gè)磁盤(pán)拇囊,一個(gè)SD卡可以看做是一個(gè)磁盤(pán)。因?yàn)榇疟P(pán)的容量有限靶橱,我們?cè)谶M(jìn)行讀寫(xiě)的時(shí)候寥袭,需要隨時(shí)查看讀寫(xiě)的進(jìn)度。
另外抓韩,我們以MT29F4G08B為例纠永,看看存儲(chǔ)器的結(jié)構(gòu)如下:
- 一頁(yè)紙上有四個(gè)內(nèi)容塊,一個(gè)內(nèi)容塊就是基本的閱讀單元谒拴,為512字節(jié)尝江,就是一個(gè)Sector。
- 一頁(yè)紙就是一個(gè)PAGE=4*512字節(jié)英上。
- 64頁(yè)訂在一起炭序,就是一本書(shū),為一個(gè)BLOCK苍日,也就是說(shuō)惭聂,一個(gè)BLOCK有644512字節(jié)。
- 一個(gè)圖書(shū)館一共有4096本書(shū)相恃,也就是4096個(gè)BLOCK辜纲,這個(gè)圖書(shū)館的名字叫做volume。
- 但是注意拦耐,每一頁(yè)還有64字節(jié)的位置耕腾,相當(dāng)于是圖書(shū)館的導(dǎo)覽圖標(biāo)存儲(chǔ)位置。
在操作的時(shí)候杀糯,如果Sector沒(méi)有對(duì)齊扫俺,應(yīng)該怎么樣處理呢?如下圖:
我們讀取的時(shí)候固翰,I/O buffer一次性讀取一個(gè)sector狼纬,一個(gè)sector的大小可以通過(guò)FF_FS_TINY進(jìn)行設(shè)置。
從上面的圖我們可以看到骂际,如果沒(méi)有進(jìn)行sector對(duì)齊疗琉,則我們將數(shù)據(jù)截成多塊進(jìn)行傳輸。
Considerations on Flash Memory Media
大容量存儲(chǔ)器的讀寫(xiě)我們必須考慮傳輸效率歉铝,如下圖没炒,單個(gè)SECTOR的效率明顯要低于多sector傳輸效率。
所以我們要盡量用多SECTOR來(lái)進(jìn)行讀寫(xiě),如果操作一個(gè)4G的內(nèi)存卡送火,用單SECTOR和多個(gè)sector可以明顯的看出傳輸速率的差異拳话,如下圖:
強(qiáng)制進(jìn)行擦除
當(dāng)我們使用f_unlink將磁盤(pán)進(jìn)行彈出時(shí),F(xiàn)AT則處于FREE狀態(tài)种吸,但是可能數(shù)據(jù)還沒(méi)有傳輸完成弃衍,就像我們U盤(pán)播放電影時(shí)候,突然掉線(xiàn)彈出后坚俗,數(shù)據(jù)需要全部進(jìn)行擦除镜盯,我們可以使用FF_USE_TRIM來(lái)使能Trim 功能,此時(shí)猖败,CTRL_TRIM 功能將在disk_ioctl 中進(jìn)行執(zhí)行速缆。
Critical Section
如果有特殊情況打斷section的傳輸,比如udden blackout, incorrect media removal and unrecoverable disk error恩闻,此時(shí)數(shù)據(jù)傳輸失敗艺糜,比如下面的情況,我們打開(kāi)一個(gè)文件以后幢尚,當(dāng)有重命名的請(qǐng)求的時(shí)候破停,將破壞數(shù)據(jù),我們可以多加入一些同步的命令尉剩,防止數(shù)據(jù)破壞的概率真慢。
Extended Use of FatFs API
下面示范一個(gè)清空一個(gè)目錄的操作,代碼如下:
/*------------------------------------------------------------/
/ Remove all contents of a directory
/ This function works regardless of FF_FS_RPATH.
/------------------------------------------------------------*/
FILINFO fno;
//入口參數(shù):清空的具體路徑
FRESULT empty_directory (
char* path
{
UINT i, j;
FRESULT fr;
DIR dir;
//先打開(kāi)此文件
fr = f_opendir(&dir, path);
if (fr == FR_OK) {
for (i = 0; path[i]; i++) ;
path[i++] = '/';
for (;;) {
fr = f_readdir(&dir, &fno);
if (fr != FR_OK || !fno.fname[0]) break;
if (_FS_RPATH && fno.fname[0] == '.') continue;
j = 0;
do
path[i+j] = fno.fname[j];
while (fno.fname[j++]);
if (fno.fattrib & AM_DIR) {
fr = empty_directory(path);
if (fr != FR_OK) break;
}
fr = f_unlink(path);
if (fr != FR_OK) break;
}
path[--i] = '\0';
closedir(&dir);
}
return fr;
}
int main (void)
{
FRESULT fr;
FATFS fs;
char buff[256]; /* Working buffer */
f_mount(&fs, "", 0);
strcpy(buff, "/"); /* Directory to be emptied */
fr = empty_directory(buff);
if (fr) {
printf("Function failed. (%u)\n", fr);
return fr;
} else {
printf("All contents in the %s are successfully removed.\n", buff);
return 0;
}
}
具體的函數(shù)功能參考下一篇FATFS的常用接口函數(shù)理茎。