1

I am using ARM GCC for a STM32F105RC processor.
In my application I have now something like:

typedef struct
{
  uint16_t coinValue;
  uint8_t  minimumCoins;
} MIN_COIN_RENDERING;

typedef struct
{
  uint16_t coinValue;
  uint8_t  hopperType;
  uint8_t  motorDelay;
} CONFIG_HOPPER;

typedef struct
{
  MIN_COIN_RENDERING minCoinRendering[10];
  CONFIG_HOPPER hopper[5];
  uint8_t reservedFFU[X];
  //
  uint16_t crc;
} APPLICATION_CONFIG; // MUST have 128 bytes!

The first problem is how to determine correctly the number of bytes reserved FFU (marked above with an X).
If you say: X = 128 - (10 x 3 + 5 x 4 + 2) = 76, well this is not true!
The correct value for X is 66, because the compiler aligns the fields in the structures (at least with the compiler's default settings).
The overall structure must have 128 bytes, as it will be stored-to / restored-from an EEPROM. The structure is used as a shadow copy of what we have in EEPROM...

My question: Is there a way (better, flexible) to have a shadow copy (for the EEPROM) without having to mess with the reservedFFU size each time I add a new field (or change something) in the APPLICATION_CONFIG structure ?

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68

3 Answers3

3

Just write something like this:

typedef struct
{
    MIN_COIN_RENDERING minCoinRendering[10];
    CONFIG_HOPPER hopper[5];
} APPLICATION_CONFIG;

typedef struct
{
    APPLICATION_CONFIG config;
    uint8_t reserved[128 - sizeof(APPLICATION_CONFIG) - 2];
    uint16_t crc;
} EEPROM_LAYOUT;
Alexey Esaulenko
  • 499
  • 2
  • 10
  • Even though it's massively unlikely in practice, I think the compiler is still _technically_ at liberty to make EEPROM_LAYOUT overflow 128 bytes and put crc in the wrong place - the C99 standard just says "There may be unnamed padding within a structure object, but not at its beginning.", in a separate clause from "There may be unnamed padding at the end of a structure or union." – Notlikethat Oct 23 '15 at 12:56
  • 1
    there may be alignment bytes between reserved[] and crc, so this is not a totally reliable method. Suggest using the `offsetof()` (similar to `sizeof`) to get the exact location of a field in a sturct. Suggest using a `union`s where one member is 128bytes to set the locations of fields within the struct – user3629249 Oct 24 '15 at 09:53
  • @user3629249 : Very useful comment, yet please can you detail a little bit about "using `offsetof()` to get exact location of a field..."? I mean how would that help exactly? TIA. – סטנלי גרונן Oct 25 '15 at 10:56
2

The fact that you want something of a fixed size with data at specific offsets sounds a lot like you want something that's part-structure, part-array. Provided you're prepared to treat the crc slightly differently, why not have exactly that!

typedef union
{
  struct {
    MIN_COIN_RENDERING minCoinRendering[10];
    CONFIG_HOPPER hopper[5];
  };
  uint16_t raw[64];
} APPLICATION_CONFIG;

// Then e.g.
APPLICATION_CONFIG config;
config.hopper[3].motorDelay = 7; // Thanks to anonymous structures
uint16_t *crcptr = &config.raw[63];
Notlikethat
  • 20,095
  • 3
  • 40
  • 77
  • **UP** :) ... and I bet there is a fancy way to include the `uint16_t CRC` into the raw part of that union, _right_? – סטנלי גרונן Oct 23 '15 at 16:54
  • Well, the idea of `struct { uint16_t data[63]; uint16_t crc; }` does come to mind, but I feel positively dirty suggesting it... – Notlikethat Oct 23 '15 at 17:16
  • Why? Any drawback related to it?... or something else that I'm missing? – סטנלי גרונן Oct 24 '15 at 09:52
  • I was thinking of `struct { uint8_t data[126]; uint16_t crc; }` as CRC function usually asks for a byte* data-block, so it would be handy. Otherwise casting will be required, I suppose... – סטנלי גרונן Oct 24 '15 at 10:00
  • Duh, how didn't I think of that? - it is a bit clearer and less horrible. Just be wary of going down the slippery slope that leads to [things like this](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/mm_types.h#n46) ;) – Notlikethat Oct 24 '15 at 14:07
0

The first problem is how to determine correctly the number of bytes reserved FFU (marked above with an X).

As you have mentioned yourself regarding the fact that compiler aligns the fields in the structure and which is in fact implementation-defined, then you have to make sure to go through you compiler settings to figure out how exactly it aligns the data. Maybe it features some statements to change the structure alignment settings.(I haven't dig deep enough in ARM GCC to say it for sure).

My question: Is there a way (better, flexible) to have a shadow copy (for the EEPROM) without having to mess with the reservedFFU size each time I add a new field (or change something) in the APPLICATION_CONFIG structure ?

Unfortunately, I can't give a straight answer to this question. From my perspective, it depends on the solution of the first part of your question.

lazyneuron
  • 537
  • 5
  • 12