Okay, so I'm still not reading the entire post before replying. *sigh* You've done a lot of work to avoid setting EIND in the inline assembly. You know the call is to high memory, so just set it in the inline assembly. > Is there a way, how to say to a GCC compiler, that asm part modifies specific regs ?
Yup. The Inline Assembly entry in the Avr-Libc manual (online at http://www.nongnu.org/avr-libc/user-manual/inline_asm.html) shows the asm syntax as: asm(code : output operand list : input operand list [: clobber list]); The "clobber list" tells the compiler that the given list of registers will be changed and registers not saved (English: clobber == "to hit seriously, to damage") by the assembly code and should be saved if the compiler wants them. Since you are calling a C function, you should also read about the "call used" and 'call saved" registers and make sure those are also in your clobber list (see the FAQ #13 (http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage) ). I've taken a stab at modifying your first inline to take these to ideas into account. The call-used and call-saved registers are *not* in the clobber list. asm volatile ( "ldi r24, 0x01" "\n\t" // set up EIND "out 0x3C, r24" "\n\t" "movw r30,%3" "\n\t" //indirect call address "movw r20,%0" "\n\t" //load args "movw r22,%1" "\n\t" "movw r24,%2" "\n\t" "eicall" "\n\t" :: "r" (size), "r" (p_data), "r" (address), "r" (call_address) : "r20", "r21", "r22", "r23", "r30", "r31" ); Also note in the manual is a way to make this a function call: void CallBootFunction( uint16_t size, uint16_t* p_data, uint16_t address, uint32_t call_address) { uint16_t lower_address; lower_address = (uint16_t)((call_address >> 1UL) & 0xFFFFUL); asm volatile ( "ldi r24, 0x01" "\n\t" // set up EIND "out 0x3C, r24" "\n\t" "movw r30,%3" "\n\t" //indirect call address "movw r20,%0" "\n\t" //load args "movw r22,%1" "\n\t" "movw r24,%2" "\n\t" "eicall" "\n\t" :: "r" (size), "r" (p_data), "r" (address), "r" (lower_address) : "r20", "r21", "r22", "r23", "r30", "r31" ); } Best regards, Stu Bell DataPlay (DPHI, Inc.) ________________________________ From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Dusan Ferbas Sent: Monday, August 04, 2008 8:37 AM To: [email protected] Subject: [avr-gcc-list] eicall on ATmega2561 Hi, we are trying to call a bootloader function from application. According to data, different function is used there (eeprom, flash, SPI flash). We have a problem, because it does not work. I consulted with Andy Hutchinson a while ago, we investigated little more, but something more is needed :-). In other words it looks like EIND seeding does not work. Are we missing to setup something ? Is there a way, how to say to a GCC compiler, that asm part modifies specific regs ? For AVR, they are used to pass arguments. Or is it a better way to create an inline function ? ... it did not work leaving all work to compiler (WinAVR-20080610 used) ----------------------------------------- unsigned char eind_local = EIND; EIND = 0x3F800 >> (16 + 1); //highest LoadAddr bits (for Atmega2561 == 1, because it is a word address) BootInfoHeader->fn[id](address, p_data, size); EIND = eind_local; to be sure, what is happening (EIND seeding and restore left in C) --------------------------------------- unsigned short call_address = (unsigned short)BootInfoHeader->fn[id]; asm volatile ( "movw r30,%3" "\n\t" //indirect call "push r20" "\n\t" //preserve regs, used for args "push r21" "\n\t" "push r22" "\n\t" "push r23" "\n\t" "movw r20,%0" "\n\t" //load args "movw r22,%1" "\n\t" "movw r24,%2" "\n\t" "eicall" "\n\t" "pop r23" "\n\t" //restore regs "pop r22" "\n\t" "pop r21" "\n\t" "pop r20" :: "r" (size), "r" (p_data), "r" (address), "r" (call_address) ); the only way, how it works (push return address, push call address and make a "ret" to it, EIND is not needed) ------------------------------------- unsigned char low_address = call_address & 0xFF; unsigned char high_address = (call_address >> 8 ) & 0xFF; unsigned char low_pc = 0x38; //computed from .lst and .map unsigned char high_pc = 0xFA; asm volatile ( "push r20" "\n\t" "push r21" "\n\t" "push r22" "\n\t" "push r23" "\n\t" "push %5" "\n\t" "push %6" "\n\t" "ldi r20,lo8(1)" "\n\t" "push r20" "\n\t" "push %3" "\n\t" "push %4" "\n\t" "push r20" "\n\t" "movw r20,%0" "\n\t" "movw r22,%1" "\n\t" "movw r24,%2" "\n\t" "ret" "\n\t" "pop r23" "\n\t" "pop r22" "\n\t" "pop r21" "\n\t" "pop r20" :: "r" (size), "r" (p_data), "r" (address), "r" (low_address), "r" (high_address), "r" (low_pc), "r" (high_pc) ); Dusan Ferbas www.etech.cz <http://www.etech.cz/>
_______________________________________________ AVR-GCC-list mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
