操作系統(tǒng):rt-thread
文件系統(tǒng):Fat16
硬件平臺(tái):stm32f103c8
描述:利用mcu的ram虛擬一個(gè)U盤,用于存儲(chǔ)即時(shí)小數(shù)據(jù),通過usb以u(píng)盤的方式供上位機(jī)讀取。
一:硬盤篇
1、硬盤物理結(jié)構(gòu):
盤片(platter):硬盤由很多盤片組成,每個(gè)盤片的每個(gè)面都有一個(gè)讀寫磁頭(heads)。N個(gè)盤片,就有2N個(gè)面,對(duì)應(yīng)2N個(gè)磁頭,從0、1、2……開始編號(hào);
磁道:同一個(gè)盤片不同半徑的同心圓為磁道(注意,是指圓周線或圓環(huán));
柱面(cylinders):不同盤片相同的磁道,構(gòu)成柱面,由外至里編號(hào)0、1、2……
扇區(qū)(sector):每道磁道被劃分成幾十個(gè)扇區(qū),通常,一個(gè)扇區(qū)容量為512B,并按照一定規(guī)則編號(hào)1、2、3……
簇:另外,由于扇區(qū)實(shí)在太多了,文件分配表沒辦法一一描述,所以,就把一定數(shù)量的扇區(qū)分為一個(gè)簇。所以文件系統(tǒng)是以一簇為最小單位的。
注意:磁頭和柱面都是從0開始編號(hào)的,扇區(qū)搞毛特殊從1開始。
總扇區(qū)數(shù)量=柱面數(shù)×磁頭數(shù)×每道扇區(qū)
2、磁盤引導(dǎo):
下圖是一個(gè)4個(gè)分區(qū)的硬盤,開頭的主引導(dǎo)記錄就是上面介紹的MBR,其中4個(gè)分區(qū)表分別指出了4個(gè)分區(qū)的位置,上位機(jī)獲取MBR之后,就知道了硬盤的總體結(jié)構(gòu),包括硬盤的大小、每個(gè)分區(qū)的位置、每個(gè)分區(qū)的大小等等。
隱藏區(qū)(hidden sector):在分區(qū)之前的部分,而下面介紹的MBR就是隱藏區(qū)的第一個(gè)扇區(qū)。隱藏區(qū)不是必須的,它和系統(tǒng)啟動(dòng)有關(guān),如果僅僅是作為存儲(chǔ),那么隱藏區(qū)可以沒有。比如,標(biāo)題說的用RAM虛擬的U盤。
注意:在我理解中,嚴(yán)格地說,隱藏區(qū)應(yīng)該是指每個(gè)分區(qū)之內(nèi),位于保留區(qū)之前的扇區(qū),也就是說,每個(gè)分區(qū)都有一套隱藏區(qū)+保留區(qū)。只是在唯一存儲(chǔ)介質(zhì)的第一個(gè)分區(qū)的隱藏區(qū)才是必須的,因?yàn)樗枰糜谙到y(tǒng)的啟動(dòng)。而其他分區(qū)的隱藏區(qū)則一般被省略。如果不被省略,比如SD的開頭就有一部分隱藏區(qū),這時(shí),引導(dǎo)代碼部分是空的(因?yàn)椴恍枰鼇碜鱿到y(tǒng)啟動(dòng)),只有DPT分區(qū)表才有意義,用于劃分SD的分區(qū)情況。
MBR(master boot record)扇區(qū):即主引導(dǎo)記錄,有時(shí)也叫主引導(dǎo)扇區(qū),位于硬盤的0柱面0磁頭1扇區(qū),也就是所謂是第0扇區(qū),也是整個(gè)存儲(chǔ)介質(zhì)的首個(gè)扇區(qū)。其中前446字節(jié)為引導(dǎo)程序,緊跟著的是64字節(jié)的硬盤分區(qū)表DPT,最后2個(gè)字節(jié)是“0x55 0xAA”,為磁盤有效結(jié)尾標(biāo)志。
MBR 是不隨操作系統(tǒng)的不同而不同的,具有公共引導(dǎo)特性。(在雙系統(tǒng)中,一般先裝Windows再裝linux,原因是,linux會(huì)修改這段代碼,讓用戶可以選擇進(jìn)去哪個(gè)系統(tǒng),但Windows卻是沒有,如果后裝Windows,那么linux的引導(dǎo)就會(huì)被忽略??)
(1)0x000-0x1bd:mbr引導(dǎo)代碼(有些地方也叫MBR??),446字節(jié),pc的bios執(zhí)行完自舉之后,會(huì)將cpu控制權(quán)交給此間的446個(gè)字節(jié)的loader程序;
(2)0x1be-0x1fd:DPT分區(qū)表,64字節(jié),每16字節(jié)描述一個(gè)分區(qū),所以硬盤的主分區(qū)+擴(kuò)展分區(qū)不能大于4個(gè),另外擴(kuò)展分區(qū)數(shù)不能大于1。(現(xiàn)實(shí)中,不止4個(gè),其實(shí)是擴(kuò)展分區(qū)里面分出來的邏輯分區(qū),對(duì)于邏輯分區(qū)的問題上面的鏈接也有提到,可以參考。)
0x1fe-0xff:0x55 0xAA。
主引導(dǎo)記錄部分如下表:
偏移(字節(jié)) |
長(zhǎng)度(字節(jié)) |
說明 |
0x00 |
3 |
跳轉(zhuǎn)指令(跳過開頭一段區(qū)域) |
0x03 |
8 |
OEM名稱(空格補(bǔ)齊)。MS-DOS檢查這個(gè)區(qū)域以確定使用啟動(dòng)記錄中的哪一部分?jǐn)?shù)據(jù) [3] 。常見值是IBM 3.3 (在“IBM”和“3.3”之間有兩個(gè)空格)和MSDOS5.0 . |
0x0b |
2 |
每個(gè)扇區(qū)的字節(jié)數(shù)。基本輸入輸出系統(tǒng)參數(shù)塊從這里開始。 |
0x0d |
1 |
每簇扇區(qū)數(shù) |
0x0e |
2 |
保留扇區(qū)數(shù)(包括啟動(dòng)扇區(qū)) |
0x10 |
1 |
文檔分配表數(shù)目 |
0x11 |
2 |
最大根目錄條目個(gè)數(shù) |
0x13 |
2 |
總扇區(qū)數(shù)(如果是0,就使用偏移0x20處的4字節(jié)值) |
0x15 |
1 |
介質(zhì)描述
0xF8 |
單面、每面80磁道、每磁道9扇區(qū) |
0xF9 |
雙面、每面80磁道、每磁道9扇區(qū) |
0xFA |
單面、每面80磁道、每磁道8扇區(qū) |
0xFB |
雙面、每面80磁道、每磁道8扇區(qū) |
0xFC |
單面、每面40磁道、每磁道9扇區(qū) |
0xFD |
雙面、每面40磁道、每磁道9扇區(qū) |
0xFE |
單面、每面40磁道、每磁道8扇區(qū) |
0xFF |
雙面、每面40磁道、每磁道8扇區(qū) |
同樣的介質(zhì)描述必須在重復(fù)復(fù)制到每份FAT的第一個(gè)字節(jié)。有些操作系統(tǒng)(MSX-DOS 1.0版)全部忽略啟動(dòng)扇區(qū)參數(shù),而僅僅使用FAT的第一個(gè)字節(jié)的介質(zhì)描述確定文件系統(tǒng)參數(shù)。
|
0x16 |
2 |
每個(gè)文檔分配表的扇區(qū)(FAT16) |
0x18 |
2 |
每磁道的扇區(qū) |
0x1a |
2 |
磁頭數(shù) |
0x1c |
4 |
隱藏扇區(qū) |
0x20 |
4 |
總扇區(qū)數(shù)(如果超過65535,參見偏移0x13) |
0x24 |
4 |
每個(gè)文檔分配表的扇區(qū)(FAT32)。擴(kuò)展基本輸入輸出系統(tǒng)參數(shù)塊從這里開始。 |
0x24 |
1 |
物理驅(qū)動(dòng)器個(gè)數(shù)(FAT16) |
0x25 |
1 |
當(dāng)前磁頭(FAT16) |
0x26 |
1 |
簽名(FAT16) |
0x27 |
4 |
ID(FAT16) |
0x28 |
2 |
Flags(FAT32) |
0x2a |
2 |
版本號(hào)(FAT32) |
0x2c |
4 |
根目錄啟始簇(FAT32) |
0x2b |
11 |
卷標(biāo)(非FAT32) |
0x30 |
2 |
FSInfo扇區(qū)(FAT32) |
0x32 |
2 |
啟動(dòng)扇區(qū)備份(FAT32) |
0x34 |
12 |
保留未使用(FAT32) |
0x36 |
8 |
FAT文件系統(tǒng)類型(如FAT、FAT12、FAT16) |
0x3e |
2 |
操作系統(tǒng)自引導(dǎo)代碼 |
0x40 |
1 |
BIOS設(shè)備代號(hào)(FAT32) |
0x41 |
1 |
未使用(FAT32) |
0x42 |
1 |
標(biāo)記(FAT32) |
0x43 |
4 |
卷序號(hào)(FAT32) |
0x47 |
11 |
卷標(biāo)(FAT32) |
0x52 |
8 |
FAT文件系統(tǒng)類型(FAT32) |
0x1FE |
2 |
扇區(qū)結(jié)束符(0x55 0xAA) |
DPT分區(qū)表:
表1 圖2分區(qū)表第一字段 |
字節(jié)位移 |
字段長(zhǎng)度 |
值 |
字段名和定義 |
0x01BE |
BYTE |
0x80 |
引導(dǎo)指示符(Boot Indicator) 指明該分區(qū)是否是活動(dòng)分區(qū)。 |
0x01BF |
BYTE |
0x01 |
開始磁頭(Starting Head) |
0x01C0 |
6位 |
0x01 |
開始扇區(qū)(Starting Sector) 只用了0~5位。后面的兩位(第6位和第7位)被開始柱面字段所使用 |
0x01C1 |
10位 |
0x00 |
開始柱面(Starting Cylinder) 除了開始扇區(qū)字段的最后兩位外,還使用了1位來組成該柱面值。開始柱面是一個(gè)10位數(shù),最大值為1023 |
0x01C2 |
BYTE |
0x07 |
系統(tǒng)ID(System ID) 定義了分區(qū)的類型,詳細(xì)定義,請(qǐng)參閱圖4 |
0x01C3 |
BYTE |
0xFE |
結(jié)束磁頭(Ending Head) |
0x01C4 |
6位 |
0xFF |
結(jié)束扇區(qū)(Ending Sector) 只使用了0~5位。最后兩位(第6、7位)被結(jié)束柱面字段所使用 |
0x01C5 |
10位 |
0x7B |
結(jié)束柱面(Ending Cylinder) 除了結(jié)束扇區(qū)字段最后的兩位外,還使用了1位,以組成該柱面值。結(jié)束柱面是一個(gè)10位的數(shù),最大值為1023 |
0x01C6 |
DWORD |
0x0000003F |
相對(duì)扇區(qū)數(shù)(Relative Sectors) 從該磁盤的開始到該分區(qū)的開始的位移量,以扇區(qū)來計(jì)算 |
0x01CA |
DWORD |
0x00DAA83D |
總扇區(qū)數(shù)(Total Sectors) 該分區(qū)中的扇區(qū)總數(shù) |
3、FAT分區(qū)原理:
下面終于開始說FAT。
對(duì)于一個(gè)存儲(chǔ)介質(zhì),隱藏區(qū)之后,才是文件系統(tǒng)的起始部分,以保留區(qū)開頭。
FAT文件系統(tǒng)的結(jié)構(gòu)是按照這個(gè)方式排列的:保留區(qū)、FAT區(qū)、副FAT區(qū)、根目錄區(qū)、數(shù)據(jù)區(qū)。
(1)、保留區(qū)(Reserved Region)
保留區(qū)就是分區(qū)的開始扇區(qū)到FAT表之前的扇區(qū),注意,保留區(qū)是位于分區(qū)之內(nèi),每個(gè)分區(qū)的開頭都會(huì)有一個(gè)保留區(qū)。而保留區(qū)的第一個(gè)扇區(qū)必須是BPB。如果隱藏區(qū)為0,那么BPB將位于第0扇區(qū)。
DBR(Dos Boot Record):即操作系統(tǒng)引導(dǎo)記錄,通常位于分區(qū)的第0個(gè)扇區(qū),共512個(gè)字節(jié)(特殊情況也要占用其它保留扇區(qū))。在這512個(gè)字節(jié)中,其實(shí)又是由跳轉(zhuǎn)指令,廠商標(biāo)志和操作系統(tǒng)版本號(hào),BPB(BIOS Parameter Block),擴(kuò)展BPB,os引導(dǎo)程序,結(jié)束標(biāo)志幾部分組成。 以用的最多的FAT32為例說明分區(qū)DBR各字節(jié)的含義。見圖:
對(duì)應(yīng)解釋見下表:
表3 FAT32分區(qū)上DBR中各部分的位置劃分 |
字節(jié)位移 |
字段長(zhǎng)度 |
字段名 |
對(duì)應(yīng)圖8顏色 |
0x00 |
3個(gè)字節(jié) |
跳轉(zhuǎn)指令 |
|
0x03 |
8個(gè)字節(jié) |
廠商標(biāo)志和os版本號(hào) |
|
0x0B |
53個(gè)字節(jié) |
BPB |
|
0x40 |
26個(gè)字節(jié) |
擴(kuò)展BPB |
|
0x5A |
420個(gè)字節(jié) |
引導(dǎo)程序代碼 |
|
0x01FE |
2個(gè)字節(jié) |
有效結(jié)束標(biāo)志 |
|
其實(shí),圖中,除了黑色部分,其他部分同MBR是一樣的,可以直接查看上面對(duì)MBR內(nèi)容的分析表格。
需要注意的是:
1)跳轉(zhuǎn)指令:EB xx 90,也就說第0和第2為分別是EB和90,至于具體意義,沒有暫時(shí)沒有深究;
2)對(duì)應(yīng)MBR,最大的區(qū)別是,DBR沒有分區(qū)表DPT!
(2)、FAT區(qū)
即文件分配表,有兩份,第二份是第一份的備份。文件分配表每項(xiàng)代表一個(gè)簇,由于fat16使用兩字節(jié)即16位來描述一個(gè)簇,所以最多只能管理65536個(gè)簇,又由于每簇最大只有32kB,所以使用fat16的時(shí)候,每個(gè)分區(qū)最大容量是2G。分區(qū)表的大小可以在DBR里設(shè)置。
(3)、根目錄區(qū):
第二個(gè)FAT表(即備份FAT)后面緊接著的下一個(gè)扇區(qū),就是根目錄區(qū)的開始。存放目錄項(xiàng),每個(gè)目錄下為32個(gè)字節(jié),記錄一個(gè)文件或目錄的信息(長(zhǎng)文件名例外)。目錄項(xiàng)所占的扇區(qū)與可以容納的目錄項(xiàng)有關(guān),一般為512項(xiàng),將占“512(目錄項(xiàng)數(shù))×32/512(扇區(qū)大小)”個(gè)扇區(qū)。但是目錄項(xiàng)×32一定是扇區(qū)大小512的整數(shù)倍。
32字節(jié)目錄項(xiàng)內(nèi)容如下表:
字節(jié)偏移 |
長(zhǎng)度 |
描述 |
0x00 |
8 |
DOS文件名(附加空格)
第一個(gè)字節(jié)可以是下面的特殊數(shù)值:
0x00 |
這個(gè)條目有用并且后面沒有被占用條目 |
0x05 |
最初字符確實(shí)是0xE5 |
0x2E |
'點(diǎn)'條目;'.'或者'..' |
0xE5 |
這個(gè)條目曾經(jīng)被刪除不再有用。取消刪除文檔工具作為取消刪除的一步必須使用一個(gè)正常的字符取代它。 |
|
0x08 |
3 |
DOS文件擴(kuò)展名(空格補(bǔ)齊) |
0x0b |
1 |
文檔屬性
第一個(gè)字節(jié)可以是下面一些特殊值:
位 |
掩碼 |
描述 |
0 |
0x01 |
只讀 |
1 |
0x02 |
隱藏 |
2 |
0x04 |
系統(tǒng) |
3 |
0x08 |
卷標(biāo) |
4 |
0x10 |
子目錄 |
5 |
0x20 |
檔案 |
6 |
0x40 |
設(shè)備(內(nèi)部使用,磁盤上看不到) |
7 |
0x80 |
沒有使用 |
屬性值0x0F用來表示長(zhǎng)文件名條目。
|
0x0c |
1 |
保留,NT使用(參見后面) |
0x0d |
1 |
創(chuàng)建時(shí)間,最小時(shí)間分辨率:10ms單位,數(shù)值從0到199。 |
0x0e |
2 |
創(chuàng)建時(shí)間。小時(shí)、分鐘和秒根據(jù)后面的圖示描述進(jìn)行編碼:
位 |
描述 |
15-11 |
小時(shí)(0-23) |
10-5 |
分鐘(0-59) |
4-0 |
秒/2(0-29) |
注意秒只保存了2秒的分辨率。更細(xì)分辨率的文檔創(chuàng)建時(shí)間在偏移0x0d處。
|
0x10 |
2 |
創(chuàng)建日期。年、月和日根據(jù)后面的圖示編碼:
位 |
描述 |
15-9 |
年(0 = 1980, 127 = 2107) |
8-5 |
月(1 = 1月,12 = 12月) |
4-0 |
日(1 - 31) |
|
0x12 |
2 |
最近訪問時(shí)間;參見偏移0x0e處的描述。 |
0x14 |
2 |
FAT12和FAT16中的EA-Index(OS/2和NT使用),F(xiàn)AT32中第一個(gè)簇的兩個(gè)高字節(jié) |
0x16 |
2 |
最后更改時(shí)間;參見偏移0x0e處的描述。 |
0x18 |
2 |
最后更改日期; 參見偏移0x10處的描述。 |
0x1a |
2 |
FAT12和FAT16中的第一個(gè)簇。FAT32中第一個(gè)簇的兩個(gè)低字節(jié)。 |
0x1c |
4 |
文檔大小 |
(4)、文件和目錄數(shù)據(jù)區(qū)
目錄項(xiàng)接著的第一個(gè)扇區(qū)就是真正存放文件數(shù)據(jù)或是目錄的位置了。
二:FAT16
其實(shí)和上面的介紹差不多。不過這是從文件系統(tǒng)邏輯概念來解釋,而前面更偏于物理位置。
保留區(qū) |
文檔
分配表#1 |
文檔
分配表#2 |
根目錄 |
其他所有數(shù)據(jù)...
剩下磁盤空間 |
- 保留扇區(qū),位于最開始的位置。第一個(gè)保留扇區(qū)是引導(dǎo)區(qū)DBR(分區(qū)啟動(dòng)記錄)。它包括一個(gè)稱為基本輸入輸出參數(shù)塊的區(qū)域(包括一些基本的文件系統(tǒng)信息尤其是它的類型和其它指向其它扇區(qū)的指針),通常包括操作系統(tǒng)的啟動(dòng)調(diào)用代碼。保留扇區(qū)的總數(shù)記錄在引導(dǎo)扇區(qū)中的一個(gè)參數(shù)中。引導(dǎo)扇區(qū)中的重要信息可以被DOS和OS/2中稱為驅(qū)動(dòng)器參數(shù)塊的操作系統(tǒng)結(jié)構(gòu)訪問。
- FAT區(qū)域。它包含有兩份文檔分配表,這是出于系統(tǒng)冗余考慮,盡管它很少使用,即使是磁盤修復(fù)工具也很少使用它。它是分區(qū)信息的映射表,指示簇是如何存儲(chǔ)的。
- 根目錄區(qū)域。它是在根目錄中存儲(chǔ)文檔和目錄信息的目錄表。在FAT32下它可以存在分區(qū)中的任何位置,但是在早期的版本中它永遠(yuǎn)緊隨FAT區(qū)域之后。
- 數(shù)據(jù)區(qū)域。這是實(shí)際的文檔和目錄數(shù)據(jù)存儲(chǔ)的區(qū)域,它占據(jù)了分區(qū)的絕大部分。通過簡(jiǎn)單地在FAT中添加文檔鏈接的個(gè)數(shù)可以任意增加文檔大小和子目錄個(gè)數(shù)(只要有空簇存在)。然而需要注意的是每個(gè)簇只能被一個(gè)文檔占有,這樣的話如果在32KB大小的簇中有一個(gè)1KB大小的文檔,那么31KB的空間就浪費(fèi)掉了。
總結(jié):拿SD卡來講吧,給xp格式化之后的SD卡物理結(jié)構(gòu)如下:隱藏區(qū)+保留區(qū)+FAT+副FAT+根目錄區(qū)+數(shù)據(jù)區(qū) 1、隱藏區(qū):包括MBR(主引導(dǎo)記錄)和DPT(分區(qū)表),不過這里的MBR是空的,因?yàn)椴恍枰南到y(tǒng)啟動(dòng)。上位機(jī)首先讀取這個(gè)512字節(jié),根據(jù)DPT,知道分區(qū)情況,根據(jù)這些接著直接跳到第一分區(qū)的位置讀取第一個(gè)分區(qū); 2、保留區(qū)和FAT:這是上位機(jī)讀取分區(qū)的第一部分內(nèi)容,從而知道分區(qū)的情況,根據(jù)BDR知道根目錄的位置;然后去讀根目錄。 3、根目錄區(qū):讀取分區(qū)的根目錄,可以知道分區(qū)的文件結(jié)構(gòu),然后根據(jù)對(duì)應(yīng)的FAT,讀到一個(gè)文件的內(nèi)容。注意,在根目錄里記錄了文件的開始扇區(qū),而這個(gè)邏輯開始扇區(qū),是以2開頭的,估計(jì)0和1已經(jīng)被保留所用。
前面說了一大堆關(guān)于FAT16和硬盤的東西,其實(shí)是為下面做準(zhǔn)備的。因?yàn)槲矣X得用RAM虛擬U盤,一要熟悉fat,二要熟悉USB協(xié)議。
前面介紹fat,下面應(yīng)該就說USB了,但我對(duì)USB的了解非常膚淺,沒辦法從協(xié)議的角度來記錄,只能簡(jiǎn)單的針對(duì)這次開發(fā)記錄一下,以備后用吧。
1、要了解USB的設(shè)備、配置、接口、端點(diǎn)等知識(shí)點(diǎn),和對(duì)應(yīng)的各種描述符;
2、然后了解枚舉的過程,數(shù)據(jù)線D+,D-,差分?jǐn)?shù)據(jù)傳輸,NRZI編碼,還有一些數(shù)據(jù)包;
3、一個(gè)很好用的總線監(jiān)控軟件,可以用它來監(jiān)控USB的通信過程,對(duì)開發(fā)很有用:Bus Hound;
4、USB設(shè)備分類:顯示器Monitors, 通訊設(shè)備Communication device, 音頻設(shè)備Audio, 人機(jī)輸入Human input, 海量存儲(chǔ)Mass storage。而這次我們用的應(yīng)該就是Mass storage;
……
本程序是從一個(gè)MSD卡程序中改過來的,準(zhǔn)確來說應(yīng)該是奮斗版的U盤程序修改過來的。
關(guān)鍵點(diǎn):
1、建立DBR數(shù)組(操作系統(tǒng)引導(dǎo)記錄):
扇區(qū)大。512;
每簇扇區(qū)數(shù):1;
保留扇區(qū)數(shù):1;
根目錄項(xiàng):16,因?yàn)?6×32,剛好一個(gè)扇區(qū);
小扇區(qū)數(shù):8,因?yàn)橛肦AM虛擬的U盤,自然很小,其實(shí)我只用到5個(gè)扇區(qū);
每FAT扇區(qū)數(shù):1;
隱藏扇區(qū)數(shù):0,因?yàn)椴恍枰狹BR,主引導(dǎo)記錄;
大扇區(qū)數(shù):0,fat16小容量沒有用到;
2、FAT數(shù)組
FAT表以“F8 FF FF FF”開頭,為介質(zhì)描述單元。接著每2字節(jié)代表一簇,不過簇的標(biāo)號(hào)是從2開始的,也就是說FAT表的4、5字節(jié)代表第2簇(順序其實(shí)就是首簇),6、7字節(jié)代表第3簇,以此類推;
我現(xiàn)在fat表如下:
F8 FF FF FF FF FF 00 00 ……
綠色就是代表第2簇,它的值代表文件的占用的下一個(gè)簇的簇號(hào),ffff表示這是文件的最后一個(gè)簇。因?yàn)槲覀兪且粋(gè)小文件,一個(gè)文件只用一個(gè)簇,所以這個(gè)就是FFFF。0000表示此簇沒有被分配。
例如,如果這里不是FFFF,而是0500(低位在前),則表示,文件的下一個(gè)簇的簇號(hào)是5,系統(tǒng)就會(huì)查詢fat的第5簇的位置,重復(fù)上面的動(dòng)作,知道遇到FFFF,表示這里是文件的最后一簇。
3、根目錄數(shù)組
這里根據(jù)前一篇根目錄的格式,建立一個(gè)盤符根目錄(就是插入電腦的時(shí)候盤符的名字),接著是一個(gè)文件目錄(因?yàn)檫@里只需要一個(gè)文件),起始簇為2;
4、數(shù)據(jù)數(shù)組
用于存文件的數(shù)據(jù)。
RAM虛擬的U盤結(jié)構(gòu)是這樣的:
DBR(1扇)-|- FAT(1扇)-| -副FAT(1扇)-|- 根目錄(1扇)-|- 數(shù)據(jù)(4扇,其實(shí)只用1扇的一點(diǎn)而已,小文件嘛)
pc上顯示的空間大小是2k,原因是8個(gè)扇區(qū)中,數(shù)據(jù)占了4扇,而扇區(qū)的大小為512字節(jié),所以大小是2k。
只需修改讀寫函數(shù)。讀函數(shù)這樣修改,當(dāng)讀的index為512×0是,發(fā)送DBR表;當(dāng)為512×1時(shí),發(fā)FAT,當(dāng)為512×3時(shí),發(fā)送根目錄;當(dāng)為512×4時(shí),發(fā)送數(shù)據(jù)。其他用00 00 00 00 ……來填充。
寫函數(shù)的修改:只允許寫修改數(shù)據(jù)和根目錄部分,其他時(shí)候直接返回失敗標(biāo)志。
需要注意的是,為了節(jié)省RAM,DBR、FAT、都可以用const定義,但根目錄和數(shù)據(jù)數(shù)組最好用非const全局定義,原因是上位機(jī)在讀取文件的時(shí)候,會(huì)修改根目錄的“最近訪問時(shí)間”。
另外,如果在pc機(jī)上把文件刪掉,再重新建立的時(shí)候,根目錄可不是簡(jiǎn)單的覆蓋,而且還有清空FAT的對(duì)應(yīng)標(biāo)志。所以,我這里實(shí)現(xiàn),可以刪除文件,但再重新新建的時(shí)候,這個(gè)文件是沒有被成功記錄到虛擬的U盤的,估計(jì),把FAT也改成可修改狀態(tài)就可以實(shí)現(xiàn),但是,這次項(xiàng)目不需要用到這點(diǎn),所以沒有去試。
這次實(shí)現(xiàn)存入janho程序庫“Mass_Storage(用ram虛擬u盤fat16)”中,備用。
注:根目錄的文件名不能用小寫,否則出錯(cuò),暫時(shí)不知原因所在。