we are trying to call a bootloader function from application. According
to data, different function is used there (eeprom, flash, SPI
flash).
We have a problem, because it does not work. I consulted with Andy
Hutchinson a while ago, we investigated little more, but something more
is needed :-).
In other words it looks like EIND seeding does not work.
Are we missing to setup something ?
Is there a way, how to say to a GCC compiler, that asm part modifies
specific regs ?
For AVR, they are used to pass arguments.
Or is it a better way to create an inline function ?
...
it did not work leaving all work to compiler (WinAVR-20080610 used)
-----------------------------------------
unsigned char eind_local = EIND;
EIND = 0x3F800 >> (16 + 1); //highest LoadAddr bits
(for Atmega2561 == 1, because it is a word address)
BootInfoHeader->fn[id](address, p_data, size);
EIND = eind_local;
to be sure, what is happening (EIND seeding and restore left in C)
---------------------------------------
unsigned short call_address = (unsigned
short)BootInfoHeader->fn[id];
asm volatile (
"movw r30,%3" "\n\t"
//indirect call
"push r20"
"\n\t" //preserve regs, used for
args
"push r21" "\n\t"
"push r22" "\n\t"
"push r23" "\n\t"
"movw r20,%0" "\n\t"
//load args
"movw r22,%1" "\n\t"
"movw r24,%2" "\n\t"
"eicall" "\n\t"
"pop r23"
"\n\t" //restore regs
"pop r22" "\n\t"
"pop r21" "\n\t"
"pop r20"
::
"r" (size),
"r" (p_data),
"r" (address),
"r" (call_address)
);
the only way, how it works (push return address, push call address and
make a "ret" to it, EIND is not needed)
-------------------------------------
unsigned char low_address = call_address & 0xFF;
unsigned char high_address = (call_address >> 8 ) &
0xFF;
unsigned char low_pc =
0x38;//computed from
.lst and .map
unsigned char high_pc = 0xFA;