0

I am working on a bootloader for a PIC24HJ series MCU.

While going through the linker script I noticed something, tried a google search, searched documentation, GCC linker documentation, I'm out of ideas. Anyway, going through this tutorial, step 13 has the following:

.application_ivt __APP_IVT_BASE :
{
SHORT(ABSOLUTE(__reset)); SHORT(0x04); SHORT((ABSOLUTE(__reset) >> 16) & 0x7F); SHORT(0);

SHORT(DEFINED(__OscillatorFail) ? ABSOLUTE(__OscillatorFail) : ABSOLUTE(__DefaultInterrupt)); SHORT(0x04); 
SHORT(DEFINED(__OscillatorFail) ? (ABSOLUTE(__OscillatorFail) >> 16) & 0x7F : (ABSOLUTE(__DefaultInterrupt) >> 16) & 0x7F); SHORT(0);

SHORT(DEFINED(__AddressError) ? ABSOLUTE(__AddressError) : ABSOLUTE(__DefaultInterrupt)); SHORT(0x04); 
SHORT(DEFINED(__AddressError) ? (ABSOLUTE(__AddressError) >> 16) & 0x7F : (ABSOLUTE(__DefaultInterrupt) >> 16) & 0x7F); SHORT(0);

SHORT(DEFINED(__NVMError    ) ? ABSOLUTE(__NVMError) : ABSOLUTE(__DefaultInterrupt)); SHORT(0x04); 
SHORT(DEFINED(__NVMError    ) ? (ABSOLUTE(__NVMError) >> 16) & 0x7F : (ABSOLUTE(__DefaultInterrupt) >> 16) & 0x7F); SHORT(0);

...

The question is about SHORT(0x04) (then SHORT(0x00)) after every interrupt address. This is also the case in the default linker script file. I understand taking the lower 16 bits of the address, then the upper 8 (or rather 7) bits in the next location, but why are there the 0x04 and the 0x00 staggered in there?

Thanks.

nurchi
  • 770
  • 11
  • 24
  • I haven't looked this up and verified it, so I'm not writing this as an answer, but from memory that byte is part of the hardware address, and it means it's putting the interrupt in the "segment" at 0400, but the code is going to use the short form of the address. – david Aug 10 '23 at 02:47
  • That's the only thing that came to mind, that it must be some sort of a marker or something, but wanted to confirm. Thanks. – nurchi Aug 10 '23 at 03:08
  • The entries in the vector table are actually GOTO instructions that will jump to the corresponding interrupt handler code. The 0x04 and 0x00 are the fixed parts of the encoding of the GOTO instruction. In an assembly source file, you'd just write things like `GOTO __reset` to generate these instructions, but linker scripts have no access to the instruction definitions so this has to be done manually. – jasonharper Aug 10 '23 at 03:13
  • @jasonharper, that makes sense, but I don't believe that 0x04 will give you a GOTO command on a PIC24 ??? And I don't think most of the vectors are GOTO? Only a GOTO at 00000 ? – david Aug 10 '23 at 04:17
  • Having another look at the disassembly and playing with those bytes, I can confirm that `0x04` as the MSB of the opcode makes the instruction a `GOTO` while `0x00` makes it a `NOP` (even if there is an address there). Strangest thing I noticed though, after the bootloader finishes flashing the main app firmware, the `0x040400` (reset vector at address 0) is replaced with `0x000400` thus making the bootloader (and the main app) unbootable after a power cycle. In the flash function, there is code to prevent any modification to addresses below `0x2000`. – nurchi Aug 10 '23 at 17:47
  • @david, regarding "And I don't think most of the vectors are GOTO? Only a GOTO at 00000 ?" question, it seems that the reset vector (at 0) needs to have the `0x04` as MSB, the other vectors don't seem to care. I find some linker scripts doing it as per my question, others just placing `LONG(ABSOLUTE(__OscillatorFail))` (extras not shown for brevity and readability) that result in the generated address taking the form of `0x001234`, and not `0x041234`. – nurchi Aug 10 '23 at 17:52

0 Answers0