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

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

[avr-gcc-list] eicall & EIND


From: Dusan Ferbas
Subject: [avr-gcc-list] eicall & EIND
Date: Mon, 30 Jun 2008 13:14:12 +0200

Hi guys,

we have 2 issues with eicall instruction on ATmega2561 platform.

1st is, that a call to a constant bootloader (BL) location is compiled with eicall instruction without setting EIND register.
2nd is, that in BL area, indexed call /that is compiled with eicall/ seems not to work, when used from application area.
We tried both WinAVR-20071221 and WinAVR-20080610.

I noticed, that even on ATmega128, call was compiled with all unused PC bits set to 1.
Does it mean, that we should set all "1"s in EIND ?

ad 1) same c code works on ATmega128
ATmega128 way:
-------------------------
typedef int boot_loader_send(unsigned  char *, unsigned  char *, short);
#define boot_loader_data_send ((boot_loader_send*) 0x3F80A)

...
rslt = boot_loader_data_send(workbuf, buf, len);
(compiled with simple call)

2561 solution
------------------
- code for 128 generates eicall
- using a static inline wrap function with asm call
        - it is optimized (arguments are not used, so they are not prepared in registers)
        - preparing registers in a "called" rtn did not work (however i believe that is nearly the same as a next working case)
- finally we created a rtn in an external .c module (see code with asm jmp below)
-> anyone knows an easier way ?


ad 2) works from BL area, does not from an application
following is called both from BL when XMODEM is used over a UART and also from an application
it works from BL, but does not, when called from an application
        - when indexed call was replaced with a list of calls in switch-case, it works (but we do not fit in BL area :-) )

init
         BootInfoHeader->fn[0] = FlashPage;
         BootInfoHeader->fn[1] = EEprom_write_page;
call
        unsigned char eind_local = EIND;
        EIND = 0x3F800 >> (16 + 1); //highest bit of LoadAddr (for ATmega2561 == 1, because in words)
         BootInfoHeader->fn[section_id](address, (unsigned short *)p_received_data, pagesize);
        EIND = eind_local;


code for ad 1) case
-------------------------------
int boot_loader_data_send(unsigned char *p_WorkBuffer, unsigned char *received_data_p, unsigned short data_length)
{
         p_WorkBuffer = p_WorkBuffer;
         received_data_p = received_data_p;
         data_length = data_length;
        
//      int      rslt;

//      asm volatile (  "movw r20,%3" "\n\t"
//                                          "movw r22,%2" "\n\t"
//                                          "movw r24,%1" "\n\t"
//                                          "call 0x3F00A" "\n\t"
//                                          "movw %0,r24" :
//                                          "=r" (rslt) :
//                                          "r" (p_WorkBuffer),
//                                          "r" (received_data_p),
//                                          "r" (data_length));

        asm volatile ("jmp 0x3F00A");

//      return rslt;
}

======================================
At 02:27 4.6.2008, Andy H wrote:
I cant answer your question fully. ...

Anatoly is adding support for 256 on version gcc 4.3 and gcc 4.4. He or Eric may provide you a better way to do call. (Even if it needs asm /macro wrapper)

Dusan Ferbas wrote:
Hi,

I am using WinAVR-20071221, because none of the most recent toolchains produces a runnable code for our application.

Our bootloader starts at 0x3f800 (2kB).
In its code, we are using function[id](...) construction.
This is compiled with eicall instruction, but no EIND register is set.
Is there a way, how to tell the compiler, that code is linked in upper half of flash ?
In bootloader code we can live with EIND=1 at its init.

But when we have a call from our application, neither EIND is set, even address is not divided by 2 (WinAVR bug #1959227).
Probably some far attribute should be applied ?
When compiled for ATmega128 (with 0x1f806), it works ...

typedef void boot_loader_init(unsigned  char *);
#define boot_loader_data_init           ((boot_loader_init *)0x3F806)
...
  boot_loader_data_init(buffer);
...


Dusan


Dusan Ferbas
www.etech.cz

reply via email to

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