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

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

Re: [avr-gcc-list] Why are we using EICALL and EIJMP for AVR256?


From: Andrew Hutchinson
Subject: Re: [avr-gcc-list] Why are we using EICALL and EIJMP for AVR256?
Date: Thu, 17 Dec 2009 19:30:28 -0500
User-agent: Thunderbird 2.0.0.23 (Windows/20090812)

Thanks for information and link!

I believe the wiki is misleading or refers to an earlier version of avr-gcc

For 256 devices avr-gcc uses linker trampolines to allow 16 bit function pointers to reach any function located anywhere in address map.

The EIND is set to zero by gcc. (Trampolines are located in lower memory)
When a function pointer is assigned the address of function (in upper memory), a full sized jump to the function is added to trampoline table.
The function pointer gets the 16 bit address of this entry.

When the jump occurs - using EICALL, it will jump to trampoline using 16 bit address and EIND set to zero. The trampoline JMP will then take it to the function. If the function is in lower memory, the trampoline is not created by linker (though I have not checked that!)

This basic mechanism could use ICALL or IJMP - since they work on lower memory.

Only if you want to have trampolines above first 64Kwords or want to call directly a function without trampoline, then EICALL is essential and EIND has to change. Somehow boot loaders fall into this category and AVR-GCC thus uses EICALL to support this.

There are a couple of oddities - which I hope to resolve.

First is that function pointer arithmetic of any kind is doomed - the handling is gcc is wrong and will give differing results depending on constructs used and optimization. Secondly, there are a few missed optimization of jump/call - where a direct call could be used instead of EICALL.

Andy


Dusan Ferbas wrote:
Hi, your case is, that a bootloader (BL) uses trampolines.

I described a case in this list (June 2008 and Mar 2009), where an application calls a BL, where eicall resides. There is a wiki page about it: http://www.ethernut.de/nutwiki/Nut/ATmega256x

Because of enabled interrupts during time, when BL is called, we are using:
#ifdef atmega2561
        unsigned char eind_local;       // asm ("r17");

        eind_local = EIND;
EIND = 0x3F800 >> (16 + 1); //highest bit (for atmega2561 == 1, because in words)
#endif
BootInfoHeader->fn[BootInfoHeader->SectionID](BootInfoHeader->address, (unsigned short *)received_data_p, BootInfoHeader->pagesize);
#ifdef atmega2561
        EIND = eind_local;
#endif

Dusan

At 14:35 15.12.2009, address@hidden wrote:
Thanks, it would be nice if this was documented.

I noticed it when reviewing addressing modes and a omission in call patterns.

void  (*fptr)();

fptr = main;

(*fptr)();  //Will use EICALL - should be CALL main


which become readily apparent with inlined code.


Andy



---- Sean D'Epagnier <address@hidden> wrote:
> On 12/14/09, Andrew Hutchinson <address@hidden> wrote:
> > The patterns for AVR mega 256 use EICALL an EIJMP
> >
> > Both require EIND to be set to provide upper address bits
> >
> > However, we are using linker trampolines for both, so in either case the
> > 16 bit jump or call is to the trampolines.
> >
> > Are not the trampolines always located in first 128Kbytes? Thus we
> > should be using ICALL and IJMP and not needing to set use EIND at all.
> >
> > What have I miss-understood?
> >
>
> Hi,
>
> Yes this confused me a lot too, but the reason is because the
> trampoline is not in the first 128kbytes for a bootloader, so if the
> compiler uses eijmp and eicall, then it is possible to do indirect
> calls there too, but it still works fine in normal code.
>
> Sean






reply via email to

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