Friday, 18 March 2011

Moving from FAT16 (SD) to FAT32 (SDHC) – Part 2 – Addressing Differences

In a previous blog I discussed moving from a FAT16 based SD card to a FAT32 based SDHC card.

In that blog I went through the differences in Initialisation procedures between the different SD Specification.

In this blog I’ll detail the differences in Addressing schemes between the devices and the two File Systems.

FAT32 Addressing Changes

Due to how the addressing scheme in FAT16 is organised, a top limit exists at 2GB. In order to allow the FAT File System to expand in capacity, various changes have been made to the File System, including expanding and altering registers entries.

The Boot Sector Entry:

The Boot Sector Entry or BSE, holds critical information regarding the partition’s layout. The following table shows the layout of the FAT16 BSE;

Offset Item Length Notes
00h Jump Code 3 Bytes Contains executable Machine code to allow the Host System to jump past the BSE
03h OEM ID 8 Bytes The system name which formatted the device
0Bh Bytes Per Sector 2 Bytes Normally 0x2000
(512 )
0Dh Sectors Per Cluster 1 Byte  
0Eh No of Reserved Sectors 2 Bytes  
10h No of FATs 1 Byte The Number of FAT Entries
11h Max Root Directory Entries 2 Bytes For SD Cards this is usually 0x2000
(512)
13h Total Sectors in Partition 2 Bytes Only set if the device is < 32Mb.
Will likely be unset 0x0000
15h Media Type 1 Byte 0xF8 = Hard Drive
16h Sectors Per FAT 2 Bytes Used for reaching the Root Directory
18h Sectors Per Track 2 Bytes  
1Ah No of Heads 2 Bytes  
1Ch No of Hidden Sectors 4 Bytes Number of hidden sectors between the start of the disk and the BSE
20h No of Sectors in a Partition 4 Bytes Total number of Sectors in the Partition
24h Logical Drive No 1 Byte 0x80 for Hard Drives
25h Head No 1 Byte Usually 0x00
26h Extended Boot Signature 1 Byte Always 0x29 denoting that Serial No, Label and Type fields are valid
27h Serial No 4 Bytes Serial No of the Device
2Bh Partition Name 11 Bytes  
36h FAT Type 8 Bytes  
3Eh Executable Boot Code 448 Bytes Allows the host to find the first file which boots the system
0x01FE Executable Signature 2 Bytes End of BSE

The BSE has been modified and expanded to allow the File System to expand past the 2GB limit. The modified BSE for FAT32 is shown below. The value positions which have changed or been added are shown in red;

Offset Item Length Notes
00h Jump Code 3 Bytes Contains executable Machine code to allow the Host System to jump past the BSE
03h OEM ID 8 Bytes The system name which formatted the device
0Bh Bytes Per Sector 2 Bytes Normally 0x2000
(512 )
0Dh Sectors Per Cluster 1 Byte  
0Eh No of Reserved Sectors 2 Bytes  
10h No of FATs 1 Byte The Number of FAT Entries
11h Max Root Directory Entries 2 Bytes Always 0 for FAT32
13h Total Sectors in Partition 2 Bytes Only set if the device is < 32Mb.
Will likely be unset 0x0000
15h Media Type 1 Byte 0xF8 = Hard Drive
16h Sectors Per FAT 2 Bytes Always 0 for FAT32
18h Sectors Per Track 2 Bytes  
1Ah No of Heads 2 Bytes  
1Ch No of Hidden Sectors 4 Bytes Number of hidden sectors between the start of the disk and the BSE
20h No of Sectors in a Partition 4 Bytes Total number of Sectors in the Partition
24h Sectors Per FAT 4 Bytes

Defines the total number of Sectors contained
in each FAT on the SD Card.
e.g. 0x911D0000 = 7569 Sectors per FAT

28h Flags 2 Bytes Defines flags for Active FAT Copy and Mirroring
2Ah Version 1 Byte Version of FAT Drive
2Ch Cluster of Root Dir 4 Bytes

Defines the Start Cluster of the Root Directory
on the SD Card.
e.g.0x02000000 = 2

30h FS Info Sector 2 Bytes Defines the first Sector of the File System Info.
32h Backup BSE Sector 2 Bytes Defines the First Sector of the Backup BSE
34h Reserved 12 Bytes Reserved Bytes
40h Drive Number 1 Byte Logical Drive Number of Partition
41h Reserved 1 Byte Reserved Byte
42h Boot Signature 8 Bytes

Defines the Boot Signature of the File system
in use on the SD card.
If this value is not 0x29, then the total number
of hidden sectors is halved, and all values
in the Boot Sector Entry after 0x001E should
be ignored.
e.g. 0x29 = Boot Signature = 41d

43h Volume Serial No 4 Bytes

Defines the Serial number of the File system
on the SD Card.
e.g.0x3CF21620 = Serial Number = 242223241

47h Volume Label 11 Bytes

Defines the Volume Label of the File system.
e.g. "NO NAME    "

52h File System Type 8 Bytes

Defines the type of File System on the SD card.
e.g. "FAT32   "

As can be seen above, there have been quite a few changes to the BSE structure to cope with the conversion from FAT16 to FAT32.

Calculating the Root Directory Address (FAT16):

The formula use to calculate the Root Directory Address for FAT16 is;

RDE Address = FAT1 Start Address +
              ((No of FATs(From BSE) *
              Sectors Per FAT(From BSE)) *
             
Bytes Per Sector(From BSE))

Calculating the Root Directory location (FAT32):

From the FAT32 BSE table above, we can see we have a new field at offset 2Ch; “Cluster of Root Directory”.

This field allows us to Jump from the first Data Cluster of File System directly to the Root Directory. We do of course need to calculate the first Data Cluster Address. The formula for this is;

First Data Cluster =
         (
Partition 1 Start Sector(From MBR) +
         Reserved Sectors(From BSE) +
        
(No of FATs(From BSE) *
            Sectors Per FAT(From BSE))) *
         Bytes Per Sector(From BSE)

Once we have the address of the first Data Cluster, we are then able to calculate the address of the Root Directory. This is accomplished simply by applying the formula used for locating a File or Folder;

File / Folder Address =
         Cluster 1 Start Address +
         (((File/Folder Start Cluster–2) *
         Secs/Cluster(From BSE)) * 512)

Thus we apply the formula above feeding in the Root Directory Start Cluster, to obtain the Root Directory Address.

SD Card Addressing Change

As SD cards have increased in size, it has become necessary for devices to use a different addressing scheme. FAT16 devices address on a Byte by Byte level. However, as devices have grown, this has become an unmanageable number.

This change of course affects the use of CMD17 – Block Read. Where the argument supplied is a 4 byte address to read data from. As mentioned above, for normal SD Cards this address is a byte unit address. However, the larger devices now use a Sector by Sector addressing scheme. Of course, this requires that the Host system take this into account when addressing the card, such that it must record which type of card is connected and make a decision of which addressing scheme to use based upon this. The card type is detected using the ACMD41 command sequence detailed in my previous blog.

The simplest way to handle this difference in code, is to simply check the card size before passing the address to CMD17. If the Host is connected to an SDHC device, then simply divide the Byte Address by 512 to reach the Sector Address.

Alternatively, rather than multiplying all Sector Address locations by the Bytes/Sector value, the Host may simply check the Card Type, if a Standard SD card is connected, then simply multiply the Sector Address by the Bytes/Sector value to reach the Byte Address.

This decision will no doubt depend upon whether you are writing code from scratch or upgrading already existing code.

2 comments:

  1. Hi, nice info!.

    I have a question, if i wanted to write in the byte 262144 of a card, with an SDSC card shall i use 0x40000 as the address and with an SDHC card shall i use 0x200? is that what you mean with the addressing change?

    Thanks in advance!!!

    ReplyDelete
  2. Hi, I would also like to know the solution to Juan question.

    for example, if I want to read data from byte address 0x000 40 8000 (as seen from hex editor/winhex), then I should use address 408000/200 = 0x00002040 when using CMD17/CMD18?

    Thanks.

    ReplyDelete