Hello, i use winavr gcc for programming atmega2561 microcontroller.
2561 has 256 K program memory our code works good below 128 K but when our code becomes larger than 128 K byte, does not work properly. this is because eicall assembler command. there must be an EIND=1 command before accessing the memory after 128 K. when this is done, there is no problem.
you have to fix this problem as soon as possible. we cannot use half of our program memory right now.
*** Bug 38550 has been marked as a duplicate of this bug. ***
*** Bug 38551 has been marked as a duplicate of this bug. ***
Bug #38057 reports the same issue. Perhaps this should be changed to CONFIRMED and one of the bug reports set as duplicate.
*** Bug 38057 has been marked as a duplicate of this bug. ***
I can confirm this is indeed a problem. I am developing a bootloader for ATxmega128A1 (128 KB app flash + 8 KB bootloader = 136 KB flash total). My code:
#define PROG_START 0x0000
This emits the following:
# Notice on reset, EIND register is written to a 1 as shown here.
# I searched the entire emitted disassembly and found no other
# reference to the I/O address for EIND.
202ec: 01 e0 ldi r16, 0x01 ; 1
202ee: 0c bf out 0x3c, r16 ; 60
# Notice that Z is set to 0, as expected. However, EIND is not
# set to 0 and so the processor attempts to do the jump to
# the location specified by EIND == 1 and Z == 0, which isn't a valid
# place to jump to.
20590: e0 e0 ldi r30, 0x00 ; 0
20592: f0 e0 ldi r31, 0x00 ; 0
20594: 19 95 eicall
Presumably this will come up much more frequently now that the ATxmega processors are available: all of these have so much flash that I would imagine this will be a frequent problem.
I assume the problem happens with EIJMP which also uses EIND.
I notice that eicall / eijmp are used in libgcc.s. I wouldn't be surprised if there are bugs there, too - but did not investigate further.
My fix is simple; just set EIND = 0 before my jump. However it leaves little faith in my compiler for the application itself, since I don't know if it will work reliably on AVR with large flash space for all jumps and calls, etc.
Closed as INVALID.
In the remainder you find an ouline of how to cope with indirect jumps on devices with more than >128 KiB of code.
Actually, the flaw is that the following explanation is not yet part of the documentation, see PR50820.
* The compiler never sets EIND.
* The startup code from libgcc never sets EIND.
Notice that startup code is a blend of code from libgcc and avr-libc.
For the impact of avr-libc on EIND, see avr-libc documentation.
* The compiler uses EIND in EICALL/EIJMP instructions or might read
* The compiler assumes that EIND is not changed during startup code or
run of the application. In particular, EIND is not saved/restored in
function or interrupt service routine prologue/epilogue.
* It is legitimate for user-specific startup code to setup EIND
early, for example by means of initialization code located in
section .init3 prior to general startup code that initializes
RAM and calls constructors.
* For indirect calls to functions and computed goto, the linker will
generate stubs. Stubs are jump pads sometimes also called trampolines.
Thus, the indirect call/jump will jump to such a stub.
The stub contains a direct jump to the desired address.
* Jump pads will be generated automatically by the linker if
- the address of label is taken like so
LDI r24, lo8(gs(func))
LDI r25, hi8(gs(func))
- and if the final location of that label is in a code segment
*outside* the segment where the stubs are located.
The compiler will emit gs() relocations (short for generate
stubs) if the address of a label is taken.
* Addresses of labals are taken in the following situations:
- Taking address of of a function or code label
- Computed goto
- If prologue-save function is used, see -mcall-prologues
command line option
- Switch/case dispatch tables. If you do not want such dispatch
tables you can specify the -fno-jump-tables command line option.
- C and C++ constructors called during startup
- C and C++ destructors called during shutdown
- If the tools hit a gs() directive explained above
* The default linker script is arranged for code with EIND = 0.
If code is supposed to work for a setup with EIND != 0, a custom
linker script has to be used in order to place the sections whose
name start with .trampolines into the segment where EIND points to.
* Jumping to a non-symbolic addresse like so:
int main (void)
// Call function at word address 0x2
return ((int(*)(void)) 0x2)();
is /not/ supported. Instead, a stub has to be set up like so:
int main (void)
extern int func_4 (void);
// Call function at byte address 0x4
and the application be linked with -Wl,-defsym=func_4=0x4
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen from the domain http://volichat.com
Page where seen: http://volichat.com/adult-chat-rooms
Marked for reference. Resolved as fixed @bugzilla.