Ooo, I see a cruel prank depending on how the development team is organized!
Anyway, my application and bootloader are in the same project, so the compiler knows about the RAM for both simultaneously. The linking part is proving to be a headache between less-than-descriptive error messages and a less-than-helpful help file.
After talking with a supplier, I solved the potential brick problem my having some fixed startup code in the boot block and then protecting it with the config bits. This code checks a flag that is just outside of the protected area to determine whether to jump to the main code or to an internal copy/verify routine. The erased value goes one way, else the other. The flag is only changed when both the code and the image to copy are valid. An unexpected reset may write flash more than required, but it never runs invalid code. It does create 3 cycles of extra latency to the interrupts (LJMP, boot block is too big for BRA), but after much consideration, I think I can handle that.
I still have two problems:
1.
If I compile my code with no special linker options, it works with no errors. If I add these options, I get fixup errors:
- Code: Select all
Extra Linker Options:
-L-pBootloaderCodeMain=1000h -L-pBootloaderCodeUSB=BootloaderCodeMain -L-pBootloaderConstUSB=BootloaderCodeUSB -L-pBootloaderCode=BootloaderConstUSB -L-pBootloaderConst=BootloaderCode -L-pApplicationISR=0200h
ROM ranges:
default,-0-1FF
As best I can tell from the help file, fixup errors mean that the compiler has done its thing already and left symbolic addresses for everything, the linker has put everything where it's supposed to go, and there is now a placeholder that is too small for the address that needs to go there. It says nothing about how to fix it.
Either way, the C code still has one of these in every .c file except for the one that I'm okay with using any remaining free space:
- Code: Select all
//Relocate code into custom sections to be linked explicitly
// must be in the file itself, can't be #included
// likewise, relocated constants must be in the file itself, not in a header
#pragma psect maintext=BootloaderCodeMain
#pragma psect text%%u=BootloaderCode
#pragma psect strings=BootloaderConst //constants normally go in strings, but this pragma bumps them to stringtext; don't know why
#pragma psect stringtext=BootloaderConst //catch stringtext also
2.
Most of the project is spread across several C source files, but the startup code is written in assembly. I'd like to include that into the project as well so that I end up with one hex file to debug with and send to production. For field updates, I can split the hex file later into startup (throw away), application (download 2nd), and bootloader (download 1st). But when I add the assembly file "Startup.s" to the C project, the makefile seems to break:
- Code: Select all
make[2]: *** No rule to make target 'build/default/production/Startup.obj', needed by 'dist/default/production/Main.X.production.hex'. Stop.
make[1]: *** [.build-conf] Error 2
make[2]: Leaving directory 'C:/Users/aaron/MCP/CastleLink_V1/Main.X'
make: *** [.build-impl] Error 2
nbproject/Makefile-default.mk:75: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/aaron/MCP/CastleLink_V1/Main.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
BUILD FAILED (exit value 2, total time: 1s)
I could have the startup code in a separate project and then link the hex file into the C one, but I'd like to make sure that the jump to main() works without duplicating code and forgetting to update one of them.
![Embarrassed :oops:](./images/smilies/icon_redface.gif)
It's actually a two-stage jump that goes to the end of flash first and then from there to main(). This gives the startup code a known place to go while keeping the bootloader's starting address flexible.
The dual-project idea might work anyway if I could encode that jump in the C project. And it would keep the end of the bootloader from running over it.