I have the same prerequisites as Dave Durbin in How can I implement a dynamic dispatch table in C... except my target is AVR. Here are my constraints:
- modules are to be picked in a list, much like Linux compiled-in kernel modules
- the number of C (can be C++) modules is known at compile-time
- modules are to be statically linked (obviously)
- I want the table in program memory, not in SRAM
Typically, the table should comprise items of this type:
typedef struct jump_item {
uint16_t function_id;
void (*callback)(void);
} jump_item_t;
I have tried using custom sections as suggested in the answer but then the linker throws an error for an unknown symbol __start_myownsection
(whatever section name I use though). Of course since the code targets Linux/GCC. But I think I'm close because avr-gcc
actually can use sections, just that I haven't been able to figure out yet how to stack symbols in a user-defined section and actually pointing to the beginning of the table, as well as determine the length of the table at run-time.
How could Art's answer be adapted to AVR?
* EDIT *
I can see at least two ways to achieve what I want using sections, either with functions "attached" to a user-defined section or tables of structures (as defined above) that all will stack up in the user-defined section. My current issues are:
- unused variables are optimized away at compile-time!
- unused functions are optimized away at link-time due to linker argument
-gc-sections
, which I need to clean unused functions.
I prefer the second option, something similar to this:
module1.c:
const jump_item_t module1_table[] __attribute__((__progmem__, section("tbl_dispatch"))) =
{
{ 0x02, func11 },
{ 0x03, func12 },
...
};
module2.c:
const jump_item_t module2_table[] __attribute__((__progmem__, section("tbl_dispatch"))) =
{
{ 0x12, func21 },
{ 0x13, func22 },
...
};
Note: indices aren't to be considered relevant.
When all modules define such variables, they're optimized away as there's nowhere any reference to these. They need to stack up in section tbl_dispatch
though. So my question falls back to:
How can I tell the compiler from removing variables it "thinks" are unused but only with specific C/C++ modules?
The global command line I'm using so far is as follows:
avr-gcc -g -Wall -mcall-prologues -fshort-enums -Os \
-DF_CPU=8000000 -Wl,-relax -mmcu=... \
*.cpp *.c -o main
* EDIT *
To my disappointment, PROGMEM and custom sections don't go together. I've tried to combine them but I get disseminated jump tables in program memory... when I get these included at all. Fact is not even all tables appear in program memory.
Giving up.
Any idea welcome.