Happy New Year to everyone!
I’m working on bootloader for XMEGA with 256 kB FLASH. My bootloader has some functions, which will be eventually called by regular application code. So, as usual, I made jumptable, which is placed in bootloader code, through which my BL functions will be called. Till now, everything seems to be ok.
The problem is the application. Because bootloader code starts at 0x40000, so obviously to call bootloader function, I have to use far call/jmp or EICALL/EIJMP. The regular code, generated by avr-gcc uses EICALL:
static inline void NVM_ExecCommand_SPM(uint16_t address, uint8_t cmd)
{ ((PF_BL_TwoUInt816) (BOOTLOADERBASE/2 + 4))(address, cmd); };
2c6: 6a e1 ldi r22, 0x1A ; 26
2c8: 80 e0 ldi r24, 0x00 ; 0
2ca: 90 e0 ldi r25, 0x00 ; 0
2cc: e2 e0 ldi r30, 0x02 ; 2
2ce: f1 e0 ldi r31, 0x01 ; 1
2d0: 19 95 eicall
Of course generated code is wrong, because EIND register is not correctly set. I can do it, using a small code which will set EIND before call, and set it to zero after return. No problem with that.
However, using eicall is not very effective, as compiler has to set Z register, and I need to manually take care about EIND. So I’d like to use regular CALL, which on AVR with >128 kB of FLASH can address the whole address space. But how to enforce compiler to use call? The obvious solution is to use assembly:
static inline void NVM_ExecCommand_SPM(uint16_t address, uint8_t cmd)
{
asm volatile(
"call %[label]" "\n\t"
:: [address] "r" (address), [cmd] "r" (cmd), [label] "i" (BL_Vector1):
);
}
Works almost great, but… the compiler doesn’t treat my function as a function, I mean, the compiler doesn’t prepare registers for function parameters passing. address variable is placed in R24:R25 according to function call convention, but cmd is placed in R18, instead or R22:
2c0: 2a e1 ldi r18, 0x1A ; 26
2c2: 80 e0 ldi r24, 0x00 ; 0
2c4: 90 e0 ldi r25, 0x00 ; 0
2c6: 1e 94 00 01 call 0x40200 ;
I can manually assign registers, by moving R18, to R22 (“mov R22, %[cmd]”), but it will generate unnecessary code.
So my question is – do you know how to enforce compiler to treat my function as a function?
Of course removing static inline, and defining function code in c file will not help.