Clever macro to handle consecutive addresses with built-in static_assert
-
I'm writing code for a microcontroller in standard C and I'm compiling with GCC. My product has registers with addresses:
enum regAddr_e {
REG_A = 0,
REG_B = 2,
REG_C = 4
};typedef struct {
regAddr_e regAddr;
uint16_t regValue;
} regAddrAndValue_s;When I want to write to registers, I create an array of regAddrAndValue_s and pass it to my write function. However, I have found that I quite often write to consecutive addresses so a lot of times only the start address would be needed:
typedef struct {
regAddr_e startRegAddr;
uint16_t regValues[];
} consecutiveRegAddrAndValues_s;However, as a documentation I would like to keep all registers visible in the code. So, I would like have a macro that does something like this:
#define MY_CLEVER_MACRO(__NAME_OF_STRUCT_VARIABLE__) \
REG_A, 0x0123, \
REG_B, 0x04567, \
REG_C, 0x89ABThe macro should produce:
consecutiveRegAddrAndValues_s __NAME_OF_STRUCT_VARIABLE__ = {REG_A, {0x0123, 0x4567, 0x89AB}};
Also, if someone changes the register addresses so that a range is no longer consecutive, then I would like to throw a compile-time static_assert. Can someone please help me what MY_CLEVER_MACRO should look like?
-
I'm writing code for a microcontroller in standard C and I'm compiling with GCC. My product has registers with addresses:
enum regAddr_e {
REG_A = 0,
REG_B = 2,
REG_C = 4
};typedef struct {
regAddr_e regAddr;
uint16_t regValue;
} regAddrAndValue_s;When I want to write to registers, I create an array of regAddrAndValue_s and pass it to my write function. However, I have found that I quite often write to consecutive addresses so a lot of times only the start address would be needed:
typedef struct {
regAddr_e startRegAddr;
uint16_t regValues[];
} consecutiveRegAddrAndValues_s;However, as a documentation I would like to keep all registers visible in the code. So, I would like have a macro that does something like this:
#define MY_CLEVER_MACRO(__NAME_OF_STRUCT_VARIABLE__) \
REG_A, 0x0123, \
REG_B, 0x04567, \
REG_C, 0x89ABThe macro should produce:
consecutiveRegAddrAndValues_s __NAME_OF_STRUCT_VARIABLE__ = {REG_A, {0x0123, 0x4567, 0x89AB}};
Also, if someone changes the register addresses so that a range is no longer consecutive, then I would like to throw a compile-time static_assert. Can someone please help me what MY_CLEVER_MACRO should look like?
If you want to 'document' where you're writing to, why not just provide several functions that offer this information right in their name? E. g.;
void setreg_A(uint16_t aval);
void setreg_B(uint16_t bval);
void setreg_C(uint16_t cval);
void setreg_all(uint16_t aval, uint16_t bval, uint16_t cval);If that isn't what you want, what is? Can you show a line of code that would invoke your 'clever macro'? It's hard to say what is your intention without seeing how you're going to use it.
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)