access function pointer arrays from Program Memory...???

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear readers!

In my application I use many arrays of function pointer. It's a tricky stuff to implement an readable source of state machines. It's look like this:

typedef struct statemachine
{
INT8U state;
INT8U event;
} STATEMACHIEN_T;

typedef INT8S (* PF_FUNCTION_1) statemachine_1 (STATEMACHINE_T *ptr_state);

INT8S foo1 (INT8U *ptr_state);
....
INT8S foo12 (INT8U *ptr_state);

INT8S PF_FUNCTION_1 statemachine_1 [MAX_STATE][MAX_EVENT] =
{
/* STATE EVENT_1 EVENT_2 EVENT_3 */
/* WAITING */ { foo1, foo2, foo3 },
/* RECEIVE */ { foo4, foo5, foo6 },
/* PROCESSING */ { foo7, foo8, foo9 },
/* TRANSMITT */ { foo10, foo11, foo12 }
}

main (void)
{
STATEMACHINE_T *automate;
....

automate->state = WAITING;
automate->event = EVENT_1;

for(;;)
{
statemachine_1 [automate->state][state->event] (state);
}

}

The Problem is, these implementation uses a lot of SRAM space. How I can place these function arrays in program memory space and how I can access these function pointer and call the function?
I think it's importand to know about this possibility, because Embedded Programmers often deal with such a statemachine for communication stuff or other applications.

Maybe we can find a usefully solution?
Thank you,
Thomas

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

In your case, you have two problems, your table must to be in progmem.data (const), in your declaration, put PROGMEM

const struct STATEMACHIEN_T PROGMEM my_tbl = { ...

Compiler don't know if my_tbl is placed in program memory. you must use PRG_RDB() macro for read a byte form this table else compiler read all data from ram only.

If you have a pointer of function given in this table. you declare a pointer in ram

void (*ptrF)(void);
you initialize this variable with 2 PRG_RDB (high an low byte), and after you can call your function. you can use memcpy_P in replacment.

Frantz

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

whenever I put a definition like:

void (*ptrF)(void);

into my code, AVR-Studio (3.54 and 3.55) crashes when loading the .cof for emulation/simulation. Do you have the same problem or some workaround for this?

- Michael

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

/* ---------------------------------------------------------------
My implementation of (void) function pointer tables in flash.
When needed, any of them can be copied into pointer_table in RAM.

Hope this helps -- regards, Sean
---------------------------------------------------------------- */

// declare void_fp as a pointer to a function taking no arguments
// and returning no value

typedef void (*void_fp)(void);

// ----------- PRG_RDW - read word from code space ---------
// macro by Jiri Prchal, posted to avrfreaks web site

#define PRG_RDW(addr) ({\
unsigned short __addr16 = (unsigned short)(addr);\
unsigned int __result;\
__asm__ __volatile__ (\
"lpm" "\n\t"\
"mov %A0, r0" "\n\t"\
"adiw r30, 1" "\n\t"\
"lpm" "\n\t"\
"mov %B0, r0"\
: "=r" (__result)\
: "z" (__addr16)\
: "r0"\
);\
__result;\
})

// macro to make function pointer table in flash

#define make_fpt(table_name,f1,f2,f3 ) \
prog_int table_name[3] = \
{ (unsigned int) f1 , (unsigned int) f2 , (unsigned int) f3 }

// declare function pointer table in RAM as a global

void_fp pointer_table[3] ; // array of pointers to void functions

// function to copy function pointer table from flash ROM into RAM

void load_pointer_table( const prog_int table[3] )
{
BYTE i ;

for( i = 0 ; i < 3 ; i++ )
pointer_table[i] = (void_fp) PRG_RDW( &table[i] ) ;
}

// declare functions

void function1( void ) { /* ...code... */ }
void function2( void ) { /* ...code... */ }
void function3( void ) { /* ...code... */ }

// make function pointer table in flash

make_fpt
( fp_table ,
function1 ,
function2 ,
function3
) ;

void main( void )
{
unsigned char function_number ;
void_fp voidfunc_p ; // seems to be needed - see below

// copy the flash table into RAM
load_pointer_table( fp_table ) ;

// ... code to determine function_number...

// call the function referenced by function_number

voidfunc_p = pointer_table[function_number] ;
(* voidfunc_p)() ;

// Note: for some reason, in my project the compiler
// complains if I try this:

// (* pointer_table[function_number] )() ;

// (error msg I get is something like
// "unable to spill a register ... bailing"
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you very much for the explaination!

I've already implemented the methode of Frantz! I used the memcpy_P function to get the function pointer out of the Program Memory.
Thank you Frantz!

The solution from Sean looks like a nice and clearly implementation.
Thank you Sean!
But I think the problem is the global defined function array. It uses space of 'n' function pointers in Data Memory. Isn't it ?

Fazit:
Now I've saved 1078 Bytes in the Data Memory! It's so importand for me, beacause I use excessive malloc & free in my Atmega128 application.

Greetings,
Thomas

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hallo Michael!

I don't work with AVR Studio + GCC. It crashes all the time when loading the .cof Files. Maybe there will be an AVR Studio Release working with GCC and .elf Files and debugging capabilities for variables!
I'm looking forward to use AVR JTAG ICE with GDB and AVaRiCE on Linux for debugging on Chip.

Greetings,
Thomas