|
This is a quick guide on what it takes to get C18 code that is intended for use with a bootloader to be compatible with the MPLAB SIM simulator. In this case, I am modifying code written for the 18F4550 that is meant for use with the Microchip standard USB bootloader. There should also be enough information here to get you started if you need modify code for other purposes - such as making normal code work with a bootloader, or with in-circuit debugging. For bootloader compatibility, the code is shifted a bit; instead of starting at 0x0000, the reset and interrupt vectors are shifted up by 0x0800, to 0x0800 (reset), 0x0808 (high priority interrupt), and 0x0818 (low priority interrupt). The linker file is responsible for reserving the first 0x0800 bytes for the bootloader code, with a couple lines like this: CODEPAGE NAME=boot START=0x0 END=0x7FF PROTECTED CODEPAGE NAME=vectors START=0x800 END=0x0x829 |
In addition, the three vectors are remapped in the code like so:
extern void _startup (void); // See c018i.c in your C18 compiler dir #pragma code _RESET_INTERRUPT_VECTOR = 0x000800 void _reset (void) { _asm goto _startup _endasm } #pragma code
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808 void _high_ISR (void) { user_interrupt(); }
#pragma code _LOW_INTERRUPT_VECTOR = 0x000818 void _low_ISR (void) { ; }
|
So the problem here is that the code that is compiled this way is only meant to exist from 0x0800 up, with the bootloader code that is already in place taking up the first part. When you are trying to run the simulator, that bootloader code is not in place and things don't work properly; in my case, this resulted in it giving repeated stack overflows and being completely unusable. The problem is that the file c018i.o mentioned in the linker file has a reference to address 0x000000 for the reset vector. (You can view the C file, it's somewhere in the MCC18 directory) The simple solution is to just use some preprocessor directives to determine whether the reset vector is actually placed at 0x0000 or 0x0800. The code is as follows: #define SIM #ifndef SIM #pragma code _RESET_INTERRUPT_VECTOR = 0x000800 #endif void _reset (void) { _asm goto _startup _endasm } |
Quite simply, if you have the #define SIM at the top, it does not remap the reset vector to 0x0800, and instead it goes to its default location of 0x0000, and MPLAB simulation works fine; and if you just comment out the #define SIM, it goes to 0x0800 for use with the bootloader. The interrupt vectors don't need to be remapped, since they're not pointed to in any unexpected files, so MPLAB takes care of them just fine. As a sidenote, you also might want to put in some #ifdef SIM statements around some of the calls to USB-specific functions, such as USBTasks() and mInitializeUSBDriver(), since none of the USB stuff is going to work in the simulation anyway, to clean up the simulation so you're only looking at your user code.
|