11.12.5 Example of Simple Bootloader Application
A simple bootloader might look like this:
#include <xc.h>
#include "bootloader.h"
volatile int safe_to_continue = 0;
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void) {
safe_to_continue = 1;
IFS0bits.T1IF = 0;
}
/*
* will be filled in by target application
*/
void (*volatile startup_location)(void) __attribute__((section("startup"),shared));
main() {
IPC0bits.T1IP = 6;
IEC0bits.T1IE=1;
PR1 = 1000;
T1CONbits.TON = 1;
while (safe_to_continue == 0);
T1CONbits.TON = 0;
// presumably we have no communications request, and can proceed
if (startup_location) startup_location();
}
The variable startup_location
is shared and defined in the bootloader. The end application may redefine the contents of the variable, but not the address. The target application will provide an over-ridden definition of this value to be the address of its startup location. For a C application, this will be the function _reset
.
#include <xc.h>
#include <stdio.h>
#include "bootloader.h"
extern void _reset(void);
void (*volatile startup_location)(void) __attribute__((section("startup"),shared)) = &_reset;
main() {
fprintf(stderr,"Hello world\n");
}
The rest of the bootloader application could be filled-in to accept some communication and re-program the target. When the whole system starts, the NULL initialization of startup_location
may be over-written by the target application.