Disk Area Allocation Details
This topic provides details on the internal structure of the flash disk.
The flash disk has a number of areas. Each area includes one or more flash sectors. Each sector has a physical size of 264 bytes. Of those, only 256 bytes are used to store the data. The two last bytes of each sector store the checksum. Six remaining bytes are mostly left unused, except in the FRT/FAT areas (see below), where they do serve a useful function.
The flash disk has the following areas:
- BOOT sector, always at logical sector #0 (so it is the topmost physical sector of the flash — this was explained in Sharing Flash Between Your Application and Data). The boot sector contains the information about the sizes of other areas of the disk.
- File record table (FRT) area.
- File allocation table (FAT) area.
- Data area — actual data sectors of files.
- Transaction journal area — caches modified sectors during the disk transaction. This area only exists if you format the disk with the fd.formatj method.
- END BOOT sector — keeps the same data as the BOOT sector, but is located past the data area.
FRT Area
Each file record occupies 64 bytes. Therefore, each sector of the FRT area can fit four file records. Therefore, if you specify (during formatting) that you would like to have 15 different files, the fd.format (or fd.formatj) method will round this up to 16 files. This will require four sectors to fit. The actual amount of allocated sectors is always double that. This is done for sector leveling, which the fd. object takes care of internally. Also, the number of allocated sectors is never less than eight, again, for sector-leveling reasons.
The maximum number of files stored by the fd. object is 64. Thefore, the maximum size of the FRT area is (64 / 4) * 2 = 32 sectors. Hence, the size of the FRT area is always between eight and 32 sectors, depending on the maximum number of files you need to store on the disk.
FAT Area
Each FAT sector consists of 128 FAT entries, 2 bytes per entry. Therefore, each FAT sector can fit the allocation data for 128 sectors from the data area of the disk. To improve sector leveling, the number of sectors allocated for the FAT area is, again, double what's necessary. So, for every 128 sectors in the data area of the disk there are two sectors in the FAT area. At least 16 sectors are always allocated to FAT.
An example, supposing the data area has 1,100 sectors. Therefore, 1,100 / 128 = nine FAT sectors that are needed. The fd. object will allocate double this required minimum, so 18 FAT sectors will be prepared. Let's suppose now that we only have 500 data sectors. This requires four FAT sectors, eight after we double this amount. This is less than the minimal 16 FAT sectors that are always provided, so the fd. object will still allocate 16 sectors.
Allocation and Capacity Calculation Example
The fd.format method takes, as an input parameter, the total number of sectors that you wish the disk to occupy. From that, and the supplied desired max number of files, the method will work out the size of each area of the disk. Let's see this in a real example:
Supposing that you call fd.formatj(1300,41,100) — you want the disk to occupy 1,300 sectors and store 41 files. You want the journal area to have 100 free sectors. So, what will be the size of the FRT, FAT, and data areas?
First, fd.formatj deducts two sectors to account for the BOOT and the END BOOT sectors that must always be present. This leaves us with 1,298 sectors.
Next, deduct the journal area — now only 1,198 sectors are left.
Next, fd.formatj determines the size of the FRT area: 41 is rounded to 44, this works out to (44 / 4) * 2 = 22 sectors needed (this exceeds the minimum of eight so we do not need to correct this number). We have 1,198 - 22 = 1176 sectors left.
Now, how many FAT sectors do we need? 1,176 / 128 = 9.18 (i.e., 10). The actual amount will be doubled, so we need 20 sectors (exceeds the minimum of 16, so we do not need to correct this number). Therefore, we are left with 1,176 - 20 = 1,156 data sectors. This is what you will get from the fd.capacity read-only property (see Checking Disk Vitals).
One Small Caveat...
Now, let us show you one trickier example. Say, you do fd.format(1301,4). You can quickly work out that you have 1,301 sectors for the FAT and data areas combined. Now, how should this be divided?
If you had 1,300 sectors, then there would be no problem. Of them, 1,280 would go to the data area and 20 would belong to the FAT. The 10 "necessary" FAT sectors will together hold 10 * 128 = 1,280 entries — just right for the size of the data area. The number of FAT sectors is always doubled, so the FAT will get 20 sectors. Everything fits perfectly!
Now, there is no good solution for 1,301 sectors. If you give this extra one sector to the data area, then you will need two more sectors for the FAT area — and you don't have those sectors. Allocating this extra sector to the FAT is useless, because you are not increasing the number of data sectors, so you don't really need an extra FAT sector. Hence, the value of 1,301 is actually not suitable to us. The same goes for 1,302, but 1,303 is good again, because three extra sectors allow us to give one sector to the data area and add two sectors to the FAT area (the FAT always increased in "doubles," remember?).
The fd.format method avoids falling into the trap by correcting downwards the total disk size you request if it turns out to be one of the "problematic" values. So, if you do fd.format(1302,4), then the result would be as if you did fd.format(1300,4). The fd.totalsize read-only property reflects this.
Why Is There the END BOOT Sector?
The END BOOT sector exists for one purpose — to detect whether your application has encroached on the flash disk. As was already explained, on devices with shared flash memory, the firmware/application and the data area reside in the same flash IC. Data area sectors are counted from the topmost physical sector of the flash memory. Therefore, the END BOOT sector is the one "closest" to your application. Should the application become larger and take some of the space that was previously occupied by the flash disk, the END BOOT sector will be overwritten. The fd. object will detect this during mounting and return the 3 — PL_FD_STATUS_FORMAT_ERR status code.