2017年11月29日 星期三

DIY - ESP8266:ESP-12F SD Card FAT 檔案系統(四十九)

DIY - ESP8266:ESP-12F SD Card FAT 檔案系統(四十九):

SD Card 初始化和讀取 SD Card 程式完成後,這是 SD Card 的底層通訊,便開始要讀寫 SD Card 內資料,筆者剛好是使用 SanDisk 2GB SD Card(格式化後 = 1,943,990,784 Byte)記憶卡,所以便會用 FAT作編程,而且 FAT 也可以使用在一般電腦上,作後期的資料處理是非常方便。

SD Card FAT 檔案系統
在 SD Card 的 FAT 系統內,主引導記錄(Master Boot Record / MBR)、引導磁區(DOS Boot Record / DBR)、檔案配置表(File Allocation Table / FAT)和 根目錄(Root Directory)是很重要。

1. 主引導記錄(Master Boot Record / MBR): 
MBR 是放置在 SD Card 物理位址 0 的地方,MBR 是由 512 位元組組成,MBR 只佔用了其中的 446 個位元組,另外 64 個位元組交給了 DPT(Disk Partition Table 硬碟分區表),最後兩個位元組 “55,AA” 是分區的結束標誌。

SanDisk 2GB SD Card 主引導記錄(Master Boot Record / MBR)
Offset
Length
Name
Description
00H
446
啟動狀態
0=not bootable 0x80=bootable
0x1BE
1
啟動狀態
0=not bootable 0x80=bootable
0x1BF
1
分區1起始扇區數
Partition 1: Start Head
0x1C0 ~ 0x1C1
2
分區1起始扇區數
Partition 1: Start Sector / Cylinder
0x1C2
1
檔案系統
Partition Type
01h = 12bit FAT
04h = 16bit FAT (<32mb br=""> 05h = Ex MSDOS
06h = 16bit FAT (>32Mb)
0Bh = 32bit FAT (<2gb span="">
0x1C3
1
分區1結束扇區數
Partition 1: End Head
0x1C4
2
分區1結束扇區數
Partition 1: End Sector / Cylinder
0x1C6 ~ 0x1C9
4
此分區前扇區數
Start Sector Address of Partition 1, LBA Sector Address (Logical Setor 0)
0x1CA ~ 0x1CD
4
分區1總扇區數
Partition 1:Partition Length , Total Sectors in Partition
0x1CE
16
分區2扇區
Partition 2 Entry, (Defined as above)
0x1DE
16
分區3扇區
Partition 3 Entry, (Defined as above)
0x1EE
16
分區4扇區
Partition 4 Entry, (Defined as above)
0x1F0
12
保留
Reserved
01xFE
2
標籤
Signature AA 55
DPT(Disk Parameter Table)由4個分區表組成,每個16位元組。

計算總扇區 
MBR Sector 0:0x1CA ~ 0x1CD = [79 EF 3A 00] 
Sector Size = 0x1C6 = 0x003AEF79 = 3862393 
Capacity = 3862393 x 512 = 1977545216 = 1.97GB

計算引導扇區(DBR)起始位置 
Sector 0:0x1C6 ~ 0x1c9 = [87 00 00 00]
DBR = 0x1C6 = 0x00000087 = 135 

2. 引導扇區(DOS Boot Record / DBR): 
在 FAT 檔案系統中,檔案系統的資料記錄在引導磁區中(DBR)中。DBR 的放置位址,可以在主引導記錄的 0x1C6 計算出 DBR 的物理位址(扇區=0x87=135),DBR是由 512 位元組組成,DBR 中記錄著檔案系統的起始位置、大小、FAT 表個數及大小等相關資訊,最後兩個位元組 “55,AA” 是分區的結束標誌。

SanDisk 2GB SD Card 引導扇區(DOS Boot Record / DBR)
偏移 (位元組)
長度
說明 (DBR)
0x00
3
跳轉指令(跳過開頭一段區域)
0x03
8
OEM名稱(空格補齊)。MS-DOS檢查這個區域,以確定使用啟動記錄中的哪一部份資料 。常見值是IBM 3.3(在「IBM」和「3.3」之間有兩個空格)和MSDOS5.0.
0x0B
2
每個磁區的位元組數。基本輸入輸出系統參數塊從這裡開始。
0x0D
1
每叢集磁區數
0x0E
2
保留磁區數(包括啟動磁區)
0x10
1
FAT檔案分配表數目
0x11
2
最大根目錄條目個數
0x13
2
總磁區數(如果是0,就使用偏移0x20處的4位元組值)
0x15
1
介質描述
0xF8 單面、每面80磁軌、每磁軌9磁區
0xF9 雙面、每面80磁軌、每磁軌9磁區
0xFA 單面、每面80磁軌、每磁軌8磁區
0xFB 雙面、每面80磁軌、每磁軌8磁區
0xFC 單面、每面40磁軌、每磁軌9磁區
0xFD 雙面、每面40磁軌、每磁軌9磁區
0xFE 單面、每面40磁軌、每磁軌8磁區
0xFF 雙面、每面40磁軌、每磁軌8磁區
同樣的介質描述必須在重複複製到每份FAT的第一個位元組。有些作業系統(MSX-DOS 1.0版)全部忽略啟動磁區參數,而僅僅使用FAT的第一個位元組的介質描述確定檔案系統參數。
0x16
2
每個檔案分配表的磁區(FAT16
0x18
2
每磁軌的磁區
0x1A
2
磁頭數
0x1C
4
隱藏磁區
0x20
4
總磁區數(如果超過65535,參見偏移0x13
0x24
4
每個檔案分配表的磁區(FAT32)。擴充功能基本輸入輸出系統參數塊從這裡開始。
0x25
1
當前磁頭(FAT16
0x26
1
簽名(FAT16
0x27
4
IDFAT16
0x28
2
FlagsFAT32
0x2A
2
版本號(FAT32
0x2C
4
根目錄啟始叢集(FAT32
0x2B
11
卷標(非FAT32
0x30
2
FSInfo扇區(FAT32
0x32
2
啟動扇區備份(FAT32
0x34
12
保留未使用(FAT32
0x36
8
FAT檔案系統類型(如FATFAT12FAT16
0x3E
2
作業系統自啟動程式碼
0x40
1
BIOS裝置代號(FAT32
0x41
1
未使用(FAT32
0x42
1
標記(FAT32
0x43
4
卷序號(FAT32
0x47
11
卷標(FAT32
0x52
8
FAT檔案系統類型(FAT32
0x1FE
2
磁區結束符(0x55 0xAA

計算檔案配置表(FAT1)起始位置 
DBR Sector 135:0x0E ~ 0x0F = [42 18]
Reserved Sector = 0x0E = 0x1842
FAT1起始位置 = 0x87 + 0x1842 = 135 + 6210
FAT1起始位置 = 0x18C9 = 6345

3. 檔案配置表(File Allocation Table / FAT): 
FAT 檔案配置表是在 DBR + 保留分區後的位置,有兩個完全相同的 FAT(File Allocation Table, 檔案配置表)表單組成,FAT2 緊跟在 FAT1 之後,FAT 表(File Allocation Table)是一組與資料簇號對應的清單。 

FAT 是按簇(2GB FAT32 格式,簇大小 4kB ~ 32kB)來分配記憶體空間,基本單位不是位元組而是簇(Cluster),即使某個檔只有一個位元組,作業系統也會給它分配一個最小單元:即一個簇。對於大檔,需要分配多個簇。同一個檔的資料並不一定完整地存放在磁片中一個連續地區域內,而往往會分若干段,像鏈子一樣存放。這種存儲方式稱為檔的鏈式存儲。為了實現檔的鏈式存儲,檔案系統必須準確地記錄哪些簇已經被檔佔用,還必須為每個已經佔用的簇指明存儲後繼的下一個簇的簇號,對於檔的最後一簇,則要指明本簇無後繼簇。這些都是由 FAT 表來保存的,FAT 表對應表項中記錄著它所代表的簇的有關資訊:諸如是空,是不是壞簇,是否是已經是某個檔的尾簇等。

SanDisk 2GB SD Card 檔案配置表(File Allocation Table / FAT)
計算檔案配置表(FAT2)起始位置
DBR Sector 135: DBR FAT 檔案分配表數目 = 0x10 = [02]
DBR每個 FAT檔案分配表的扇區 0x24 ~ 0x27 = [DF 73 00 00] = 0x000073DF
FAT2 起始位置 = FAT1 起始位置 + 每個 FAT 檔案分配表的扇區
FAT2起始位置 = 0x18C9 + 0x000073DF = 0x8CA8 
                          = 6345 + 29663 = 36008

4. 根目錄(Root Directory):
根目錄(Root Directory)是位於資料區的開始區域,資料區時真正用於存放使用者資料的區域。資料區緊跟在 FAT2 之後,被劃分成一個個的簇。所有的簇從 2 開始進行編號,也就是說,2號簇的起始位置就是資料區的起始位置。目錄所在的磁區,都是以 32 Bytes 劃分為一個單位,每個單位稱為一個目錄項(Directory Entry ),即每個目錄項的長度都是 32 Bytes 。根目錄由若干個目錄項組成,一個目錄項佔用 32 個位元組,可以是長檔名目錄項、檔目錄項、子目錄項等。

SanDisk 2GB SD Card 根目錄(Root Directory)
位元組偏移
     長度
描述
0x00
8
DOS檔名(附加空格)
第一個位元組可以是下面的特殊數值:
0x00
這個條目有用並且後面沒有被佔用條目
0x05
最初字元確實是 0xE5
0x2E
''條目;'.'或者'..'
0xE5
這個條目曾經被刪除不再有用。取消刪除文件工具作為取消刪除的一步必須使用一個正常的字元取代它。
0x08
3
DOS副檔名(空格補齊)
0x0b
1
文件內容
第一個位元組可以是下面一些特殊值:
掩碼 + 描述
0
0x01 = 唯讀
1
0x02 = 隱藏
2
0x04 = 系統
3
0x08 = 卷標
4
0x10 = 子目錄
5
0x20 = 檔案
6
0x40 = 裝置(內部使用,磁碟上看不到)
7
0x80 = 沒有使用

內容值 0x0F 用來表示長檔名條目。
0x0c
1
保留,NT使用(參見後面)
0x0d
1
建立時間,最小時間解析度:10ms單位,數值從 0 199
0x0e
2
建立時間。小時、分鐘和秒根據後面的圖示描述進行編碼:
描述
15 - 11
小時(0-23
10 - 5
分鐘(0-59
4-0
秒/20-29
注意只保存了2秒的解析度。更細解析度的文件建立時間在偏移 0x0d 處。
0x10
2
建立日期。年、月和日根據後面的圖示編碼:
描述
15 - 9
年(0 = 1980, 127 = 2107
8 - 5
月(1 = 1月,12 = 12月)
4-0
日(1 - 31
0x12
2
最近存取時間;參見偏移0x0e處的描述。
0x14
2
FAT12 FAT16 中的 EA-IndexOS/2 NT使用),FAT32 中第一個叢集的兩個高位元組
0x16
2
最後更改時間;參見偏移 0x0e 處的描述。
0x18
2
最後更改日期; 參見偏移 0x10 處的描述。
0x1a
2
FAT12 FAT16 中的第一個叢集。FAT32 中第一個叢集的兩個低位元組。
0x1c
4
文件大小

計算根目錄(Root Directory)起始位置
DBR Sector 135: DBR FAT檔案分配表數目 = 0x10 = [02]
DBR每個 FAT 檔案分配表的扇區 0x24 ~ 0x27 = [DF 73 00 00] = 0x000073DF
根目錄起始位置 = FAT2 起始位置 + 每個 FAT 檔案分配表的扇區
根目錄起始位置 = 0x8CA8 + 0x000073DF = 0x10087 
                             = 36008 + 29663 = 65671

2017年 11月 29日 天氣報告
氣溫:22.5@ 22:30
相對濕度:百分之 85%
天氣:大致多雲