Sharing functions between application and bootloader

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a strange problem with the following function:

static inline void NVM_ExecCommand_SPM(uint16_t address, uint8_t cmd)

{

       register uint16_t address_ asm("r24") = address;

       register uint8_t cmd_ asm("r22") = cmd;


       asm volatile(

       "call  0x80B2" "\n\t"

       :: [address] "r" (address_), [cmd] "r" (cmd_), [label] "i" (BL_Vector1)

       : "r19", "r20"

       );

}

The above function (the actual function which is called by call instruction) clobbers r19 and r20, so because C has no chance to know it, I put these registers on clobber list. However, the compiler ignores this information – gcc still allocates r19 or r20 and of course, the registers are not restored after calling my function. I know that inlining my function let gcc to ignore ABI convention, but still the compiler should be aware that r19 and r20 can be modified. How to convince the compiler that it is not safe to assume that r19 and r20 are saved?

I have another interesting thing. Let’s modify the above function:

static inline void NVM_ExecCommand_SPM(uint16_t address, uint8_t cmd)

{

       register uint16_t address_ asm("r24") = address;

       register uint8_t cmd_ asm("r22") = cmd;


       asm volatile(

       "call  %[label]" "\n\t"

       :: [address] "r" (address_), [cmd] "r" (cmd_), [label] "i" (BL_Vector1)

       : "r19", "r20"

       );

}

So now, the [label] should be equal to BL_Vector1. So let’s define BL_Vector1:

#define BL_Vector1        0x80B2

But as a result I get a call to address 0x7e80b2, instead of 0x0080b2 – the code is compiled for XMEGA 32E5. Can somebody help?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why call it in Asm? Make a C call to it and the usual ABI preservation stuff will apply.

typedef void (fptr_t)(uint16_t, uint8_t);

fptr_t Exec_NVM = (fptr_t)0x80B2;

Exec_NVM(x1234, 0x02);