[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] Function pointers on > 128 KiB devices, how to?
From: |
Dale Whitfield |
Subject: |
Re: [avr-gcc-list] Function pointers on > 128 KiB devices, how to? |
Date: |
Wed, 20 Jan 2010 17:54:18 +0200 |
User-agent: |
Mutt/1.5.20 (2009-06-14) |
Hi Joerg >@2010.01.20_15:53:55_+0200
This will create an explicit trampoline. The rest of your code would
remain the same. I've used this technique in a slightly different way
previously. Caution: Compiled and inspected but not tested/simulated!
#define JMP_TABLE_ENTRY(x) __asm__ __volatile__ ("jmp "#x)
void jumptable_fn(void) __attribute__ ((naked));
void jumptable_fn(void) {
JMP_TABLE_ENTRY(foo);
JMP_TABLE_ENTRY(bar);
JMP_TABLE_ENTRY(mumble);
}
fptr jumptable[] __attribute__((progmem)) = {
jumptable_fn+0, // foo
jumptable_fn+4, // bar,
jumptable_fn+8, // mumble,
};
An advanced use for this is to allow creation of a 'jump table' that can
call functions that are not all of type fptr, ie. void fn(void).
> When porting a larger application to a 256 KiB device, we stumbled
> across our function pointers and jump tables. Consider the
> following code:
>
> #include <stdint.h>
> #include <avr/pgmspace.h>
>
> void foo(void);
> void bar(void);
> void mumble(void);
>
> typedef void (*fptr) (void);
>
> fptr jumptable[] __attribute__((progmem)) = {
> foo,
> bar,
> mumble,
> };
>
> volatile uint32_t i, j, k;
>
> void
> foo(void)
> {
> for (uint8_t x = 0; x < 200; x++) {
> i = j * 5 + k * 7;
> j = i + 32412341243;
> k = i & 0x12345678ull;
> }
> for (uint8_t x = 0; x < 200; x++) {
> i = j * 5 + k * 7;
> j = i + 32412341243;
> k = i & 0x12345678ull;
> }
> }
>
> void
> mumble(void)
> {
> for (uint8_t x = 0; x < 200; x++) {
> i = j * 5 + k * 7;
> j = i + 32412341243;
> k = i & 0x12345678ull;
> }
> for (uint8_t x = 0; x < 200; x++) {
> i = j * 5 + k * 7;
> j = i + 32412341243;
> k = i & 0x12345678ull;
> }
> }
>
> void
> bar(void)
> {
> for (uint8_t x = 0; x < 200; x++) {
> i = j * 5 + k * 7;
> j = i + 32412341243;
> k = i & 0x12345678ull;
> }
> }
>
> int
> main(int argc, char **argv)
> {
> fptr f;
>
> if (argc < sizeof jumptable / sizeof jumptable[0]) {
> f = (fptr)pgm_read_word(jumptable[argc]);
> f();
> }
>
> return 0;
> }
>
> ...compiled with (thoroughly pessimized to generate large amounts of
> code):
>
> avr-gcc -O3 -funroll-loops --param max-peeled-insns=1000000 \
> --param max-completely-peel-times=1000000 \
> --param max-unrolled-insns=1000000 \
> --param=max-completely-peeled-insns=1000000 \
> --param max-average-unrolled-insns=1000000 \
> -mmcu=atmega2560 -std=c99 -g -o foo.elf foo.c
>
> This yields:
>
> /tmp/cc1QZqci.o: In function `foo':
> /tmp/foo.c:20: warning: internal error: out of range error
>
> Trying to replace the pgm_read_word() by a pgm_read_dword_far() just
> adds more warnings about casting pointers/integers of different size,
> but doesn't help for the initial "out of range" error anyway.
>
> Is there any option at all to use function pointers for a device which
> supports code sizes > 128 KiB? I (incorrectly) assumed these were
> replaced by trampoline pointers, but apparently, they aren't.
>
> Any ideas welcome, possibly including quick&dirty inline asm hacks to
> generate the indirect call.
>
> --
> cheers, J"org .-.-. --... ...-- -.. . DL8DTL
>
> http://www.sax.de/~joerg/ NIC: JW11-RIPE
> Never trust an operating system you don't have sources for. ;-)
>
>
> _______________________________________________
> AVR-GCC-list mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>
--
Regards
Dale