10 years, 3 months ago.

Mass storage LocalFileSystem

Is there any way to activale the class LocalFileSystem to use the internal flash memory?

Question relating to:

1 Answer

10 years, 3 months ago.

Short version: No. It runs on only the two original mbeds, and then on the interface IC. Additionally the internal flash memory of these devices isn't really handy to run a filesystem on, these normally have 512B sectors, while I think the 11u68 has 4kB sectors.

This library should do an attempt at emulating localfilesystem, but you still need somewhere to store the data on.

Well, i want to mount filesystem just to download a txt with logs of temperature value, such small datas.

posted by Sergio Fernandez Santos 07 Aug 2014

Problem stays that the internal flash isn't great to mount a complete file system on. Although for something a bit similar I did recently make something.

That one had config data which had to be set (and read) by the user, but the device had normally no way for a user to affect it (no buttons, touchscreen, etc). If it would be required I can send you that part of the code, but it is in Dutch, so might not be that easy to get.

What I did was start with the USBMSD lib: https://mbed.org/handbook/USBMSD. And specifically the RAMdisk code as starting point: https://mbed.org/users/ragmondo/code/USBMSB_Ramdisk_kl25z/. That code copies also the sector info parts to RAM, but I didn't have enough RAM, and that isn't really required. So I started with that RAMdisk file system binary that is included, and optimised that a bit to be smaller.

Then my read/write functions are:

int ConfigDisk::disk_write(const uint8_t * data, uint64_t block) {
    if (block == 4)
        parseFile(data);
    return 0;
}

int ConfigDisk::disk_read(uint8_t * data, uint64_t block) {
    if (block < 4)
        memcpy(data, &disk[block*512], 512);
    else if (block == 4)
        createFile(data);
    else 
        memset(data, 0, 512);
    return 0;
}

Blocks 0-3 are filesystem blocks, they are just set during compilation. The PC can write to those sectors, for example to change the last file access date, and those writes are happily ignored. I only got one block for data, which is easy, but for large log files you will need more. Everything else is read as zeros.

When it reads my useful block, this is that function:

void ConfigDisk::createFile(uint8_t *data) {
    
    time_t seconds = clk.time(NULL);
    struct tm *curtime = localtime(&seconds);

    memset(data, 0, 512);
    data += sprintf((char*)data, "Tijd: %02d:%02d\r\n", curtime->tm_hour, curtime->tm_min);
    data += sprintf((char*)data, "Ochtend tijd: %02d:%02d\r\n", state.morningHours, state.morningMinutes);
    data += sprintf((char*)data, "Avond tijd: %02d:%02d\r\n", state.eveningHours, state.eveningMinutes);
    data += sprintf((char*)data, "Min temp: %2.1fC\r\n", state.minTemperature);    
    data += sprintf((char*)data, "Max temp: %2.1fC\r\n", state.maxTemperature);    
}

(A similar function using scanf can read the data back when the user changes it). So I have the data stored in binary somewhere (on the uCs RAM and also on battery backuped RAM on an RTC IC), and only when it needs to be viewable by a human it is written as human readable format.

This way I require a few kB of flash, which is never changed by the program, and my variables only require a few byte (well + the USBDevice lib which uses alot more. But still you don't require an actual file system).

posted by Erik - 07 Aug 2014