flipflop
A lightweight serial bootloader for PIC16F1 devices.
/**
* Main loop.
* This file holds the code that runs on reset and decides whether to start the
* bootloader or launch the user application.
*/
#include <xc.h>
#include "boot_config.h"
#include "bootloader.h"
#include "nvm.h"
// Configuration words for software control of watchdog timer.
#pragma config WDTCCS = SC
#pragma config WDTCWS = WDTCWS_7
#pragma config WDTE = SWDTEN
#pragma config WDTCPS = WDTCPS_31
// These variables hold the POR values of registers we use.
static volatile unsigned char por_osc = 0;
static volatile unsigned char por_hfosc = 0;
void
main (void)
{
// Watchdog was not cause of reset, meaning we start bootloader
if (1 == PCON0bits.nRWDT)
{
// Set watchdog prescaler to ~16s
WDTCON0bits.WDTPS = 0b01110;
// Enable WDT
WDTCON0bits.SWDTEN = 1;
// unsigned char new_osc = 0;
// Save value of clock:divider at POR
por_osc = OSCCON2;
// Save value of HFINTOSC
por_hfosc = OSCFRQ;
// if (OSCCON2bits.COSC != 0b110)
// {
// // Set clock source to HFINTOSC if not already.
// new_osc |= (0b110 << 4);
// }
// if (OSCCON2bits.CDIV != 0)
// {
// Set clock divider to 1:1 if not
// (Default value of new_osc)
// new_osc |= 0;
// }
// Set NOSC register to HFINTOSC with 1:1 divider.
OSCCON1 = 0b1100000;
// Set HFINTOSC to our needed speed (20 mhz?)
OSCFRQ = 0b110;
bootloader_start();
// Reset used registers back to POR value
OSCCON1 = por_osc;
OSCFRQ = por_hfosc;
// Disable watchdog
WDTCON0bits.SWDTEN = 0;
// Reset prescaler
WDTCON0bits.WDTPS = 0b01011;
}
// Jump to application reset vector
asm("ljmp " ___mkstr(PROG_RST_VECT));
}
// EOF //