Storing sensor data as circular buffer in non volatile memory

Hey guys,

I want to store sensor data as circular buffer in non volatile memory. I saw
https://docs.nordicsemi.com/bundle/zephyr-apis-latest/page/group_file_system_storage.html and https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/services/storage/index.html. But researching here in the devzone I can see that users have issues like here https://devzone.nordicsemi.com/f/nordic-q-a/110506/nrf5340-fcb-flash-circular-buffer-on-external-flash/530085

I was trying to use NVS but it seems that it overwrites data as stated here https://github.com/nrfconnect/sdk-zephyr/blob/a1d9a8db0ea4bbee2e69feec1140e6ce20e62f5e/samples/subsys/nvs/src/main.c#L30
But of course I need the complete history of my data.

So my question is what is currently the best approach for this?

Best

Parents Reply Children
  • Hello Michal,

    thank you. Did you already have the chance to check it?

  • Sorry, not yet.

    I will test it tomorrow.

    Best regards,

    Michal

  • Hello,

    Sorry for late reply, I have been testing it and trying to understand the failure mode.

    Just a small request, could you add a small delay while printing out the log somewhere, since it is too fast for the built-in VCOM and is dropping logs at full speed?

    I think you may also want to ask about FCB on the Zephyr discord as well, since it's a generic Zephyr OS service, people there may have an idea about the issue. 

    https://docs.zephyrproject.org/latest/project/communication.html

    Best regards,

    Michal

  • Hi Michal,

    thanks for the reply.

    I added a small delay in fcb_sector_walk_cb() but the issue seems to persist. Since you have the sources, could you double check?

     

    static int fcb_sector_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
    {
        uint16_t sector_no = *(uint16_t *)arg;
        struct FCB_sensor_data data;
        const struct flash_sector *sector = entry_ctx->loc.fe_sector;
        // Find sector index
        int idx = -1;
        for (int i = 0; i < FCB_SECTOR_COUNT; i++) {
            if (sector == &fcb_instance_sectors[i]) {
                idx = i;
                break;
            }
        }
        if (idx == sector_no) {
            // Print entry offset and length
            LOG_INF("[walk] sector %u: entry offset=0x%08lx, len=%u", sector_no, (unsigned long)entry_ctx->loc.fe_data_off, entry_ctx->loc.fe_data_len);
            // Read raw bytes for debug
            uint8_t raw[sizeof(struct FCB_sensor_data)] = {0};
            int rc = flash_area_read(entry_ctx->fap, entry_ctx->loc.fe_data_off, raw, entry_ctx->loc.fe_data_len);
            if (rc) {
                LOG_ERR("Failed to read entry with error %d", rc);
            } else {
                // Print raw bytes
                // char hexbuf[3 * sizeof(raw) + 1];
                // int hexlen = 0;
                // for (int i = 0; i < entry_ctx->loc.fe_data_len && i < (int)sizeof(raw); i++) {
                //     hexlen += snprintf(&hexbuf[hexlen], sizeof(hexbuf) - hexlen, "%02X ", raw[i]);
                // }
                // hexbuf[hexlen] = '\0';
                // LOG_INF("[walk] sector %u: raw: %s", sector_no, hexbuf);
                // Also decode as struct if possible
                if (entry_ctx->loc.fe_data_len == sizeof(struct FCB_sensor_data)) {
                    memcpy(&data, raw, sizeof(struct FCB_sensor_data));
                    LOG_INF("[walk] sector %u: sensor_ts: %llu, message_counter: %u, temp_deg_c: %d, humidity_percent: %u, pressure_kpa: %u",
                        sector_no,
                        data.payload.sensor_ts,
                        data.payload.message_counter,
                        data.payload.temp_deg_c,
                        data.payload.humidity_percent,
                        data.payload.pressure_kpa
                    );
                }
                k_sleep(K_MSEC(100)); // Small delay for log readability
            }
        }
        return 0;
    }



Related