avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Re: [avr-gcc-list] Allocating variables to a fixed address]


From: Robert von Knobloch
Subject: [Re: [avr-gcc-list] Allocating variables to a fixed address]
Date: Wed, 13 May 2009 11:35:45 +0200
User-agent: Thunderbird 1.5.0.14 (X11/20060911)

Stu Bell wrote:

> > If I had your problem, this is how I would solve it: Define a real table
> > of function pointers instead of trying to get the linker to create one
> > for you.
> > 
> >   typedef void (*TestProc) (void*);
> > 
> >   NOINLINE void test_lcd_2(void* pStr) {PGM_P string = (PGM_P) pStr;
> > prog_lcd_string2(string); }
> > 
> >   NOINLINE void test_lcd_string(void* pStr) { PGM_P string = (PGM_P)
> > pStr; prog_lcd_string(string); }
> > 
> >   NOINLINE void test_clearlcd2(void* ign) { clearlcd2(); }
> > 
> >   NOINLINE void test_lcd_hex4out(void* pByte) { uint8_t byte = *
> > (uint8_t*) pByte; return lcd_hex4out(byte); }
> > 
> >   ...
> > 
> >   const TestProc* TestTable[TEST_VECTORS] FUNCTION_SECTION = {
> >      test_lcd_2,
> >      test_lcd_string,
> >   ...
> >   };
> > 
> > You will need to modify your calls to either send the pointer to the
> > argument (this forces all calls to have a single parameter of,
> > essentially, a word) or to always send a word.  In either case, the
> > receiving routine will then cast the argument to the proper value before
> > passing it on. 
> > 
> > Do not place the routines or other constants in the same linker section
> > as the function table.  If you leave the table in a section of its own,
> > it will always be placed at the head of the section without interference
> > from anything else.
> > 
> > Calling the function requires you to pull the function out of the table
> > before calling it:
> > 
> >    #define TESTPROC_LCD_2      0
> >    #define TESTPROC_LCD_STRING 1
> >    . . .
> > 
> >    uint16_t test_proc;
> > 
> >    test_proc = pgm_read_word( (uint16_t) &TestTable[ TESTPROC_LCD_2 ] );
> >    *(TestProc*)test_proc( myarg );
> > 
> >    . . .
> > 
> > You could probably enclose the above stuff in a macro to make your code
> > far more readable:
> > 
> >    #define CallTestProc(proc,arg) \ 
> >       do {                        \
> >            uint16_t test_proc;    \
> >            test_proc = pgm_read_word( (uint16_t) &TestTable[ (proc) ] );
> > \
> >            *(TestProc*)test_proc( (arg) ); \
> >       } while (0);
> >          
> >     . . .
> > 
> >     CallTestProc( TESTPROC_LCD_2, myarg );
> > 
> > That's my inspiration for the day.  It's probably wrong somewhere, but
> > it's how I would approach the problem.
Hi Stu,

This solution, while a purer 'C' solution would require me to have all
my 'internal' functions with similar call/return requirements.
This is not, and cannot be, the case. I fear that the magig 'array of
function pointers' has only limited use and is unsuitable here.
But many thanks for your thoughts, every comment here makes me re-think
the problem, which is good.

Cheers,

Robert




reply via email to

[Prev in Thread] Current Thread [Next in Thread]