0

I'm programming an embedded system that has a number of user configurable parameters, which are stored in flash memory. I have to store a default value for each parameter as well as the user settings. Because the STM32 I use can write 64 Bits of flash memory at a time, I chose to use one word (32 Bits) for the parameter ID (used to identify value in EEPROM emulation) and the second available word for the parameter value itself. That works ok with two different structs, one for the default values and one for the user values in SRAM (which can change any time and be rewritten to flash).

But I'm not really happy with this solution, as I have to maintain two different structs in code and I have no checks, whether each struct sets all parameters or not. Also I can not reliably iterate over all parameters.

Right now it works like this:

// Typedefs for single entry as well the complete flash table
typedef struct {
  uint32_t ID;
  uint32_t value;
} FLASH_PARAM;

typedef struct {
  FLASH_PARAM param1;
  FLASH_PARAM param2;
  FLASH_PARAM param3;
  .
  .
  FLASH_PARAM paramN;
} FLASH_TABLE;

I init the struct for the default values to store in program memory like this:

FLASH_TABLE ft_default = {
  .param1 = {1, PARAM1_DEFAULT},
  .param2 = {2, PARAM2_DEFAULT},
  .
  .
  .paramN = {N, PARAMN_DEFAULT},
};

But now I see several problems:

  1. I don't get a warning if I miss an entry in ft_default. Gcc only gives warnings for missing elements in struct init if the highly confusing syntax of nameless assignment is used. This is a serious problem for me, as there are regular changes to the entries of FLASH_TABLE.
  2. There is no reliable way to iterate over all struct members. While I could access the struct like an array, this is not really defined behaviour as far as I know, so I would like to avoid that.
  3. An alternative would be to directly use an array of structs for FLASH_TABLE, iterating would be no problem then. But I want to access the FLASH_TABLE elements efficiently by name in code (ft->param1), so an array is not really an option. I could use an enum to name all array entries, but then again I have the problem of keeping enum list and default value assignment in sync...

I would prefer a clean solution where I can place all information (Name to use in code, ID to use in flash, default value) at a central table in the code. I'm not really experienced with python, but there I would probably use a dict with a list as value like this:

FLASH_PARAMS = {
"param1": [ID, default_value],
"param2": [ID, default_value],
}

I realise that this question kind of turned into a wall of text, but I hope my problem is clear now and there is some standard / default way of handling such a situation to absolutly minimize the chances of two tables not staying in sync when implementing changes.

1 Answer 1

4

We have a similar mapping issue, and for us the enumeration solution works well. That could look something like this:

enum FLASH_PARAM_IDS {
  PARAM_1,
  PARAM_2,
  .
  .
  .
  PARAM_N,
  // Insert new parameters before this line
  NUM_FLASH_PARAMS
};

FLASH_PARAM ft_default[] {
  {PARAM_1, PARAM1_DEFAULT},
  {PARAM_2, PARAM2_DEFAULT},
  .
  .
  .
  {PARAM_N, PARAMN_DEFAULT},
};

static_assert(sizeof(ft_default)/sizeof(ft_default[0]) == NUM_FLASH_PARAMS, "Number of parameter defaults does not match declared number of parameters");

You can easily iterate over all parameters and you can access individual entries with ft[PARAM_x].

This solution assumes that your IDs are consecutive and start at 0. The static_assert will give an error if there is a mismatch between the enumeration and the array entries.

1
  • 1
    I guess I will do it in a similar way then. Thank your for that suggestion.
    – jusaca
    Commented Mar 27 at 12:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.