Project logo

SimpleFS

Simple (sensor) File system.


simple FS

simple File System for embedded devices. Support fast append to file operation. The type of FS is RA (Read-Append). It is optimized for FLASH-like types of memories, where write/erase operation is much time consuming that reading.

Suppored platforms:

  • STM32
  • ESP32 (in future)
  • native C app (simulation mode)

Supported memories:

  • SPI-like: FLASH memory. Winbond W32 compatible with high capacity (1-128Mbit)
  • 1-wire: EEPROM memory. E.g. Maxim integrated DS28EC20 with maximum 20kB of capacity

Basic properies

  • Access: Read/Append
  • Write only to last file; read from any file.
  • Maximum number of files: limited by memory size only.
  • Filename is automaticaly generated based in memory ID
  • File format: CSV like, but in binary representation
    • Maximum columns in one file: configurable value
    • Length of single value: variable length, from 1B to 128B
  • Each file must has defined internal structure:
    • number of column in file
    • specification of each column type

Determination of use

  • Storing data from sensors or datasources. Supported modules:
    • Thermometer DS8B20
    • RTC clock for precise time
    • Internal Analog/Digital converter of used MCU
  • Storing primitive datatypes (size 1-128B)
    • Integers
    • String
    • Fixed point floating number

Basic configuration

Preddefined memory variants:

variant description Max. files Max. columns overheads [B]
U Ultra small 1 4 112
X eXtra small 2 8 288
S Small 8 16 1824
L Large 22 42 11824

Example

Simulation mode (without MCU)

#include <stdio.h>
#include "sensor_FS.h"

typedef struct file_sensors{
    SensorInterface_t *interfaces[10];
    int count;
}FileSensors_t;

void fill_file(FileSensors_t data, int count_records){
    SimpleFS_t *fs;
    uint8_t sensor_index = 0;
    file_add_sensor(sensor_index++, 0, data.interfaces[0]);
    file_add_sensor(sensor_index++, 0, data.interfaces[1]);
    file_add_sensor(sensor_index++, 0, data.interfaces[2]);
    FS_state fst;
    for (uint8_t i = 0; i < data.interfaces[3]->getSensorCount(); i++) {
        fst = file_add_sensor(sensor_index++, i, data.interfaces[3]);
        if (fst == STATE_ERR) {
            printf("ERR: sensor not inserted in FS");
        }
    }
    FS_commit_file_header();
    fs = FS_open_last_file();
    SensorInterface_t *sd;
    SensorValue_t *sv;

    if (fs) {
        for (int k = 0; k < count_records; k++) {
            file_data_row_begin(fs);
            for (uint8_t p = 0; p < file_get_num_parts(fs); p++) {
                RecordDescriptor_t ffd = file_column_format(fs, p);
                sd = FS_sensor_driver(ffd.sensor_type);
                if (sd != NULL) {
                    sv = sd->getValue();
                    int len = get_sensor_data_length(fs->file.format[p].value_format.meta_length);
                    file_store_data(fs, p, sv);
                }
            }
            file_data_row_commit(fs);
        }
    }
}

int main(){
    SensorInterface_t *driverOW = &owBus;
    SensorInterface_t *driverADC = &adcSensor;
    SensorInterface_t *driverTime = &timeSensor;
    SensorInterface_t *driverData = &dataSensor;
    driverOW->Init(NULL, 2);
    driverADC->Init(NULL, DUMMY_VALUE);
    driverTime->Init(NULL, FORMAT_META_FMT_SPECIAL_TIME);
    Data_HandleTypeDef dataConfig;
    dataConfig.data_type = SENSOR_TYPE_INTEGER;
    dataConfig.data_format.meta_length = FORMAT_META_LENGTH_2B;
    dataConfig.data_format.meta_format = FORMAT_META_FMT_UINT;
    dataConfig.data_format.Q.m = Q_FORMAT_NONE;
    dataConfig.data_format.Q.n = Q_FORMAT_NONE;
    driverData->Init(&dataConfig, DUMMY_VALUE);

    FS_init(NULL, NULL, 0);
    FS_write_preamble();

    FileSensors_t data;
    data.interfaces[0] = driverTime;
    data.interfaces[1] = driverADC;
    data.interfaces[2] = driverData;
    data.interfaces[3] = driverOW;

    // 1st file
    FS_create_file();
    driverOW->Init(NULL, 1);        // OW with 1 sensors
    fill_file(data, 64);

    // 2nd file
    FS_create_file();
    driverOW->Init(NULL, 2);        // OW with 2 sensors
    fill_file(data, 6);

    file_dump_memory();
    return 0;

High level API

  • File system related functions
    • FS_init() - Init the sensorFS filesystem.
    • FS_create_file() - Begin file creation procedure. No write to FLASH is perform.
    • FS_open_file() - Try open to file with given ID.
    • FS_open_last_file() - Open last file on sensorFS.
    • FS_write_preamble() - Write preamble aprt in sensorFS, if not exists.
    • FS_num_files() - Return number of files.
    • FS_detect_num_files() - Read number of files.
    • FS_commit_file_header() - Finish write information about created file.
    • FS_is_empty() - Check, that sensorFS/FLASH is empty.
    • FS_sensor_driver() - Return driver for attached sensor.
  • File related functions

    • file_add_sensor() - Add new sensor to created file.
    • file_get_num_parts() - Return number parts of opened file.
    • file_data_row_begin() - Initialize internal data structures for new data record.
    • file_store_data() - Prepare measured value to file buffer.
    • file_data_row_commit() - Write prepared measured values
    • file_record_length() - Return length of record.
    • file_column_format() - Return format of i-th sensor in datafile.
    • file_size() - Return file size in Bytes.
    • file_data_prepare() - Start value measure on all sensors.

    Author

    Juraj Ďuďák - https://gitlab.nsoric.com/juraj


Contributors 1

Juraj Ďuďák


Links

Languages

  • C 99.59%
  • CMake 0.41%

  • Last update

    30.09.2021 18:39:35

    Created at

    18.06.2021