27

Hello,

I am making an open source privacy-first fitness band for myself and I am writing the firmware now as someone relatively inexperienced at firmware development (I am an electronics engineer by trade). I get it done but sometimes I run into concept issues, especially when I start overthinking, like now that I need help with.

I have a macronix SPI NOR flash on-board that I want to use as offline activity saving, backup at low battery, etc... I am dreaming up the data structure for it. Here is the values I need to save to not lose information and what will be required for my supported features in the Bluetooth Physical Activity Monitor Service:

struct memory_map_nor {
    time_t timestamp;
    uint16_t sub_sess_id;
    uint32_t steps: 24;
    uint8_t bpm;
    float16_t spo2;
    uint16_t pulse_inter_beat_interval;
    uint16_t cadence;
    uint16_t speed;
    uint16_t activity_level;
    uint16_t activity_type;
    uint16_t temp;
};

So from this datastructure, it has a total of 28 bytes of data. This has to fit on a 256 byte page, which means 9 "rows" of data can be written per page, 144 per sector, 2304 per 64 bit block, and 147456 in total for a 32Mbit NOR.

But, I am getting confused while reading about memory structures in "normal" processors that need to read everything in 4/8-byte words via the parallel interfaces. This means that conventionally, everything has to be padded to neat structures that are divisible by 4 (32-bit) for QSPI reading. In that case, I would either have to add another 32 bits of data or pad 32 bits to every "row", making a neat 8 data "rows" per page.

OR, because I am only using single lane SPI, would this not matter and I could shove an extra datapoint in each page. The difference is 147456 data rows vs 131072 data rows. At 3s polling rate, that is 5.12 days vs 4.55 days. For my application, the difference might be useless anyway, but the band goal battery life is 2 weeks or so.

Again, maybe I am overthinking this and can just pad the data to make everything neat and fit well. Anyone have any opinions? Thanks!

top 5 comments
sorted by: hot top controversial new old
[-] Flipper@feddit.org 7 points 11 hours ago

You should rearrange your structure to group the types from biggest to smallest, otherwise you get padding you didn't want. BPM and steps for example.

Qspi in general can read single bytes. But we don't know what controller you use.

Also you probably shouldn't just read it into memory and cast it to your structure. If you ever change the layout everything breaks apart.

[-] JustEnoughDucks@feddit.nl 1 points 10 hours ago

Thanks for taking a look!

Intuitively for me, steps + bpm should be next to each other because the compiler will use bpm as the padding for the 24 bit steps. I intentionally did it that way. At least when I checked the memory addresses when testing it that was the case (there was no padding added). Wouldn't it be potentially more problematic to have a bit field with a weird bit number, 24, followed by a 16 bit member that can't be "fit" into the 32 bits that the compiler wants to assign? or is that not how it works.

I'm not quite sure what you mean by your last point. The flow would go: acquire data -> add to structure -> fill up a page worth of data (or a sector) -> write to memory. Then pulling it out would be: read from memory -> put in structure -> process -> send data via bluetooth. If I change the layout of anything, that would require a reflash of the MCU and previous data would already have been transferred over bluetooth (assuming end-user OTA flashing or just being in a vicinity of a phone and not out and about where memory saving is necessary) and would no longer be needed to be stored/pulled from memory. Or is there another case that I am totally missing?

[-] pipe01@programming.dev 3 points 10 hours ago

My recommendation is that you use a file system like littlefs which also has wear leveling built-in, and you don't have to worry about any specifics of the chip

[-] JustEnoughDucks@feddit.nl 3 points 9 hours ago

Hmmm, I used littlefs for SD card writing at work with an STM32F0 chip. It was hell working with files when tons of essential functions like appending and seeking simply didn't work in the STM HAL... Plus dealing with opening and closing files and appending files and having to seek in them to find what you want, parsing results, cleaning old files, etc... compared to simple circular buffer and a start and end address of relevant data that can be erased once every day or week depending on use. Even with a daily erase of the NOR chip, they are rated for 100k program/erase cycles which would be over 250 years before degradation starts. I am not dealing with a ton of data nor the flexibility of a full UI/ app storage where I would definitely just use littlefs.

[-] hddsx@lemmy.ca 2 points 11 hours ago

I’m going to make an assumption that this is C. The compiler should pad structures for you

this post was submitted on 18 May 2025
27 points (100.0% liked)

Programming

20196 readers
459 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 2 years ago
MODERATORS