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. 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.
Each file record occupies 64 bytes. Therefore, each sector of the FRT area can fit 4 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 4 sectors to fit. 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 8, 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 8 and 32 sectors depending on the maximum number of files you need to store on the disk.
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 against what's necessary. So, for every 128 sectors in the data area of the disk there are 2 sectors in the FAT area. At least 16 sectors are always allocated to FAT.
An example; supposing the data area has 1100 sectors. Therefore, 1100/128= 9 FAT sectors 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 4 FAT sectors, 8 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 fd.format will work out the size of each area of the disk. Let's see this on a real example:
Supposing, you call fd.formatj(1300,41,100) — you want the disk to occupy 1300 sectors and store 41 file. You want the journal area to have 100 free sectors. So, what will be the size of the FRT, FAT, and data areas?
First, the fd.format deducts 2 sectors to account for the BOOT and the END BOOT sectors that must always be present. This leaves us with 1298 sectors.
Next, decuct the journal area — now only 1198 sectors are left.
Next, the fd.format determines the size of the FRT area: 41 is rounded to 44, this works out to hat (44/4)*2= 22 sectors are needed (this exceeds the minimum of 8, so we do not need to correct this number). We have 1198-22= 1176 sectors left.
Now, how many FAT sectors we need? 1176/128= 9.18, i.e. 10. 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 1176-20= 1156 data sectors. This is what you will get from the fd.capacity R/O 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 1301 sector for the FAT and data areas combined. Now, how should this be divided?
If you had 1300 sectors, then there would be no problem. Of them, 1280 would go to the data area, and 20 will belong to the FAT. 10 "necessary" FAT sectors will together hold 10*128= 1280 entries — just right for the size of the data area. The number of FAT sectors is always doubled, so FAT will get 20 sectors. Everything fits perfectly!
Now, there is no good solution for 1301 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 1301 is actually not suitable to us. Same goes for 1302. 1303 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 (FAT always increased in "doubles", remember?).
Fd.format avoid 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 R/O property reflect 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 the 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 3- PL_FD_STATUS_FORMAT_ERR status code.