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

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

RE: [avr-gcc-list] ATmega 2561 - eicall uses "byte" address


From: Dusan Ferbas
Subject: RE: [avr-gcc-list] ATmega 2561 - eicall uses "byte" address
Date: Fri, 06 Jun 2008 01:29:02 +0200

Hi Stu,

as you said - why not to read the whole email :-).
In bootloader code we can live with EIND=1 at its init.

I now checked the case also with WinAVR-20080512. Same bug as with 20071221 (WinAVR bug #1959227 at sf.net).

Is it possible to add an attribute st. like "near" to prevent compiler using eicall and to generate icall (case 1 below) ?


--------------
case 1 (bootloader)
Problem is not with indirect call through a pointer saved in RAM.
typedef void (* WriteFN)(unsigned short page, unsigned short *data, unsigned short len);
...
        WriteFN fn[3];
...
        fn[0] = FlashPage;              //FlashPage/2 (word address) is used
...
        fn[0](page, data, len);
-> eicall generated by compiler, which does not know, that the code will be positioned with linker to an address in upper flash
(EIND=1 solves this)

        Here I would like to have an icall instruction.

--------------
case 2 (application calling fn in bootloader)
Problem is with "direct" call generated with eicall aid. I understand, that compiler cannot count with link addresses, but when address is constant even during compilation time, then it is definitely a compiler bug.

typedef void Tboot_loader_data_init(unsigned char *);
#define boot_loader_data_init ((Tboot_loader_data_init *)0x3F806)

        boot_loader_data_init(buffer)

typedef void Tboot_loader_data_init(unsigned char *);
#define boot_loader_data_init ((Tboot_loader_data_init *)(0x3F806/2))
...
    EIND = 0x3F800 >> 17;
        boot_loader_data_init(workbuf);
    EIND = 0x00;

avr-gcc (GCC) 4.2.2 (WinAVR 20071221), ATmega2561
 241 0068 81E0                  ldi r24,lo8(1)
 242 006a 8CBF                  out 92-0x20,r24
 243 006c C501                  movw r24,r10
 244 006e E3E0                  ldi r30,lo8(-1021)
 245 0070 FCEF                  ldi r31,hi8(-1021)
 246 0072 1995                  eicall

Here you can see, that a workaround was needed. To have a word address,

avr-gcc (GCC) 4.2.2 (WinAVR 20071221),  ATmega128
#define boot_loader_data_init ((Tboot_loader_data_init *)0x1F806)
 229 0054 E6E0                  ldi r30,lo8(-2042)
 230 0056 F8EF                  ldi r31,hi8(-2042)
 231 0058 0995                  icall

Also for ATmega128, no division is done by gcc 4.2.2

avr-gcc (GCC) 3.4.6,  ATmega128
#define boot_loader_data_init ((Tboot_loader_data_init *)0x1F806)
741 006c FF95 03FC              call -2042

Older gcc uses efficient std call to a word address.

Dusan

=====================
At 16:30 4.6.2008, Stu Bell wrote:
Dang, it would help if I read the entire message.

Function pointers in the bootloader. I kept my bootloader
mind-bogglingly simple precisely to avoid problems like this.
Unfortunately, many folks have a need for a far more comples bootloader
than I need.

Since the eicall is being used, why not force EIND to 1 at the beginning
of your code...

    asm volatile ( "ldi  r24, 0x01                      \n\t"
                   "out  0x3C, r24                      \n\t"
                 );

Worth a shot, eh?

Best regards,

Stu Bell
DataPlay (DPHI, Inc.)


-----Original Message-----
From: address@hidden
[mailto:address@hidden On Behalf Of
Dusan Ferbas
Sent: Tuesday, June 03, 2008 5:36 PM
To: address@hidden
Subject: [avr-gcc-list] ATmega 2561 - compiler generates eicall

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




reply via email to

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