I found this thread to be useful in debugging an ivt issue with a legacy project that built fine with an XC16 compiler suite previous to v1.26, but did not build with the updated suite. I am hoping this post will help others who have had this issue with v1.26. This is rather lengthy, so skip to the bottom to see the solution if you wish.
We are using a PIC24E series processor (PIC24EP256MC206), and working with code that utilizes a bootloader and application firmware solution. Since the PIC24E does not have an alternate ivt, and both the bootloader and application code utilize interrupts, the interrupts have to be re-routed to the application when it is running. This is done by filling the ivt with the address of the re-routing code found in the bootloader. As an example, the code to route the T1 interrupt is located in an assembly file, and looked like this:__T1InterruptRerouter: btsc RCON,#9; ;** RCON.CM is bit 9 is used to select between boot/app int
goto __T1Interrupt; ;** bootrom interrupt
goto 0x4114; ;** location of application interrupt
label (along with the other re-routing functions) went into the linker (.gld) file in the .ivt __IVT_BASE
section like this:
LONG( ABSOLUTE(__T1InterruptRerouter)); /* IRQ 3 */
The project was built with the linker option "Create default ISR". The bootloader built fine, however, when I went to merge the bootloader hex file with the application hex file (the app had the ivt table stripped out), I got this error from the srec_cat utility:srec_cat: SC020-Boot_v00.01.02.hex: 6: contradictory 0x00000008 value (previous = 0x36, this one = 0xE0)
Looking at the hex file, I saw the issue, there were two lines that allocated values to address 8:
As proof, when I selected the Project->Properties->Building->Normalize hex file
option, I got the output error noted in the original post above:(944) data conflict at address 8h between dist/default/production/Boot.X.production.hex and dist/default/production/Boot.X.production.hex
So, the linker was inserting this garbage vector for T1 into the hex file as well as my valid T1 vector. Looking at the hex file more carefully, all other vectors had this same value overwriting them (when I looked at the binary of the vector table, all vectors had 36 12 B4 in them).
I defined my own __DefaultInterrupt routine, and unchecked the option Project->Properties->xc16-ld->General->Create default ISR.
This worked to get rid of all but three of these garbage vectors, T1, U1TX, and U1RX, the three interrupts being used in the bootloader.
Here is what I found, by using the default interrupt names for these three interrupt handlers, _T1Interrupt, _U1RXInterrupt, and _U1TXInterrupt, but not installing them into the ivt, three random garbage vectors were created in the hex file anyway, each causing a conflict with the existing correct vectors (not the corresponding T1, U1RX, and U1TX vectors either, but different vectors) . When I replaced the interrupt function names with non-default names, _T1Int, _U1RXInt, and _U1TXInt, the garbage vectors went away and the hex file was fine. Apparently, the linker really really wants to put the default names into the hex file, so it does (previously it wouldn't because the name wasn't included in the linker file). So here's my solution:
- Create your own __DefaultInterrupt routine
- Uncheck the option Project->Properties->xc16-ld->General->Create default ISR
- Rename all default interrupt names, for example instead of _T1Interrupt, _T1Int, and refer to that name instead.
- Check the option Project->Properties->xc16-gcc->Preprocessing and messages->Disable ISR warn
- Check Project->Properties->Building->Normalize hex to have the build check for overlapping memory space, or uncheck to generate the hex file and look at it yourself.
So bottom line, if a default interrupt name is installed in your program, it will get installed into the hex file regardless of whether you want it there or not, even if there is already a vector there. If there is a vector already there, a "garbage" vector is generated and may (if it is inserted in the hex file after the valid vector) override the correct vector.
As an additional note, I found that (as expected) identical code could be generated by implementing an explicit ivt (using .section .ivt, code, address(0x04)
in an assembly file as noted above) or by using the linker file to remap the vectors. Using the explicit table did NOT fix the garbage vector issue unless I followed the steps outlined above.
I hope this helps someone, it was a devil of a problem...