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

[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 ?
Yup.  The Inline Assembly entry in the Avr-Libc manual (online at http://www.nongnu.org/avr-libc/user-manual/inline_asm.html) shows the asm syntax as:
 
  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.)

 


From: address@hidden [mailto:address@hidden On Behalf Of Dusan Ferbas
Sent: Monday, August 04, 2008 8:37 AM
To: address@hidden
Subject: [avr-gcc-list] eicall on ATmega2561

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


reply via email to

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