Implementing a read-only function pointer table in GCC

I want to implement a simple way to declare / define functions that should be added to a table of function pointers in R / O memory (program flash on an AVR device using GCC in particular) at compile time, and also with a default function pointer that is placed to all unused entries. For example, if I have 32 possible entries, then the following:

DEFAULTFUNC
void default_handler(...)
{
   ...
}

FUNC(28)
void handle_foo(...)
{
   ...
}

will place the pointer to handle_fooelement 28 of the function table, placing it default_handlerin another.

I looked at how avr-libc implements ISR()interrupt vectors, but it seems that it depends on some internal GCC behavior that I have not yet found to place a function pointer in a segment .vectors. How can I simulate it in code to create a table of function pointers in a segment .{,rel{,a}.}rodata, if necessary?

+4
source share
3 answers

http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html discusses the placement of variables in separate sections of the linker. They give an example of placing a uart structure in a section that was supposedly configured for a hardware address (named DUART_A):

struct duart a __attribute__ ((section ("DUART_A"))) = { 0 };

, , , , , .

+2

, , . Linux ( ). , , make - .

C ( m4, GPP script Python, awk - ...). (, #include - -) C.

C- (, C) ( C) .

GCC, . , MELT, . , ( ), C ....

+1

, , , C, __attribute__ (avr-libc , ).

, https://github.com/ndim/handler-function-table.

:

/* handler_table.h */
#ifndef HANDLER_TABLE_H
#define HANDLER_TABLE_H
#include <avr/pgmspace.h>
#define HANDLER_MAX 2
typedef void (*handler_func)(void);
extern const handler_func handler_table_P[HANDLER_MAX] PROGMEM;
#endif /* HANDLER_TABLE_H */

:

/* handler_table.c */
#include "handler_table.h"
void handler_foo(void) __attribute__((weak, alias("__handler_default")));
void handler_bar(void) __attribute__((weak, alias("__handler_default")));

const handler_func handler_talbe_P[HANDLER_MAX] PROGMEM = {
  handler_foo,
  handler_bar
};

__attribute__((weak))
void handler_default(void)
{
}

void __handler_default(void)
{
  handler_default();
}

:

/* testcase-main.c */
#include "handler-table.h"

int main()
{
  for (unsigned int i=0; i<HANDLER_MAX; ++i) {
    const uint16_t func_addr = pgm_read_word_near(handler_table_P[i]);
    const handler_func func = (handler_func) addr;
    func();
  }
}

Testcase 2 :

/* testcase-2.c */
void handler_default(void)
{ ... }
void handler_foo(void)
{ ... }

:

  • testcase-1: testcase-main.o handler-table.o

    .

  • testcase-2: testcase-main.o handler-table.o testcase-2.o

    , testcase-2.c

:

  • , .

  • , , , , . .

    - , , , .

  • AVR MCU, . , PROGMEM pgm_read_word_near.

  • , , .

    , .

    -, , , , , .

    On the other hand ... in some cases, you probably do not need a function table in the first place and several weak functions potentially overridden by non-weak functions, a problem without a table.

+1
source

All Articles