[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [avr-gcc-list] eicall on ATmega2561
From: |
Stu Bell |
Subject: |
RE: [avr-gcc-list] eicall on ATmega2561 |
Date: |
Mon, 4 Aug 2008 09:48:22 -0600 |
Okay, so I'm still not reading the entire post before replying.
*sigh*
You've done a lot of work to avoid setting EIND in the inline
assembly. You know the call is to high memory, so just set it in the
inline assembly.
> Is there a way, how to say to a GCC compiler, that
asm part modifies specific regs ?
asm(code : output operand
list : input operand list [: clobber
list]);
The "clobber list" tells the compiler that
the given list of registers will be changed and registers not saved (English:
clobber == "to hit seriously, to damage") by the assembly code and should
be saved if the compiler wants them. Since you are calling a C function,
you should also read about the "call used" and 'call saved" registers and make
sure those are also in your clobber list (see the FAQ #13 (http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage)
).
I've taken a stab at modifying your first
inline to take these to ideas into account. The call-used and call-saved
registers are *not* in the clobber
list.
asm volatile (
"ldi r24, 0x01"
"\n\t" // set up EIND
"out 0x3C,
r24" "\n\t"
"movw r30,%3"
"\n\t" //indirect call address
"movw
r20,%0" "\n\t" //load args
"movw r22,%1" "\n\t"
"movw
r24,%2" "\n\t"
"eicall"
"\n\t"
::
"r"
(size),
"r" (p_data),
"r"
(address),
"r"
(call_address)
:
"r20", "r21",
"r22", "r23", "r30", "r31"
);
Also note in the manual is a way to make
this a function call:
void CallBootFunction( uint16_t size, uint16_t* p_data,
uint16_t address, uint32_t call_address)
{
uint16_t lower_address;
lower_address = (uint16_t)((call_address >> 1UL)
& 0xFFFFUL);
asm volatile
(
"ldi r24, 0x01" "\n\t" // set up
EIND
"out 0x3C, r24" "\n\t"
"movw r30,%3" "\n\t" //indirect call
address
"movw
r20,%0" "\n\t" //load
args
"movw
r22,%1" "\n\t"
"movw r24,%2" "\n\t"
"eicall" "\n\t"
::
"r"
(size),
"r"
(p_data),
"r"
(address),
"r"
(lower_address)
:
"r20", "r21", "r22", "r23", "r30", "r31"
);
}
Best regards,
Stu Bell
DataPlay
(DPHI, Inc.)
Hi,
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;
asm volatile (
"push r20"
"\n\t"
"push r21" "\n\t"
"push r22" "\n\t"
"push
r23" "\n\t"
"push %5" "\n\t"
"push %6" "\n\t"
"ldi
r20,lo8(1)" "\n\t"
"push r20" "\n\t"
"push %3"
"\n\t"
"push %4" "\n\t"
"push r20" "\n\t"
"movw
r20,%0" "\n\t"
"movw r22,%1" "\n\t"
"movw r24,%2" "\n\t"
"ret" "\n\t"
"pop r23" "\n\t"
"pop r22"
"\n\t"
"pop r21" "\n\t"
"pop r20"
::
"r"
(size),
"r" (p_data),
"r" (address),
"r"
(low_address),
"r" (high_address),
"r" (low_pc),
"r" (high_pc)
);
Dusan Ferbas
www.etech.cz