Files
bia_microddr_fw/bootloader/src/main.c

273 lines
12 KiB
C

/*
* File: main.c
* Author: justin
*
* Created on August 9, 2019, 6:14 PM
*/
#include "usb.h"
#include "bootloader.h"
unsigned int uint_delay_counter;
/* Private prototypes */
void main(void);
void BootMain(void);
void InitializeSystem(void);
const unsigned int FlashSignatureWord __at(APP_SIGNATURE_ADDRESS) = APP_SIGNATURE_VALUE;
//const unsigned int FlashSignatureWord __at(APP_SIGNATURE_ADDRESS) = APP_SIGNATURE_VALUE;
void main(void)
{
//BootMain();
/**
* TODO: implement hardware IO-based method for forcing entry into bootloader
*/
// normal operation: verify the firmware signature is valid. if it isn't enter
// bootloader (fw update) mode so valid firmware can be flashed
DoFlashSignatureCheck:
//Check if the application region flash signature is valid
if(*(const unsigned int*)APP_SIGNATURE_ADDRESS == APP_SIGNATURE_VALUE)
{
//The flash signature was valid, implying the previous
//erase/program/verify operation was a success.
//Also make sure the first WORD of program memory in the app space
//is not blank, meaning there is an application image programmed into the device.
if(*(const unsigned int*)REMAPPED_APPLICATION_RESET_VECTOR != 0xFFFF)
{
//Go ahead and jump out of bootloader mode into the application run mode
#asm
goto REMAPPED_APPLICATION_RESET_VECTOR
#endasm
}
}
//else the application image is missing or corrupt. In this case, we
//need to stay in the bootloader mode, so the user has the ability to
//try (again) to re-program a valid application image into the device.
BootMain();
}
void BootMain(void) __at(0x30)
{
//Make sure interrupts are disabled for this code (could still be on,
//if the application firmware jumped into the bootloader via software methods)
INTCON = 0x00;
//Clear the stack pointer, in case the user application jumped into
//bootloader mode with excessive junk on the call stack
STKPTR = 0x00;
// End of the important parts of the C initializer. This bootloader firmware does not use
// any C initialized user variables (idata memory sections). Therefore, the above is all
// the initialization that is required.
//Call other initialization code and (re)enable the USB module
InitializeSystem();
//Execute main loop
while(1)
{
//Need to call USBDeviceTasks() periodically. This function takes care of
//processing non-USB application related USB packets (ex: "Chapter 9"
//packets associated with USB enumeration)
USBDeviceTasks();
ProcessIO(); //This is where all the actual bootloader related data transfer/self programming takes
//place see ProcessIO() function in the BootPIC[xxxx].c file.
}//end while
}
void InitializeSystem(void)
{
UserInit();
USBDeviceInit();
}
// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************
// The USB firmware stack will call the callback functions USBCBxxx() in response to certain USB related
// events. For example, if the host PC is powering down, it will stop sending out Start of Frame (SOF)
// packets to your device. In response to this, all USB devices are supposed to decrease their power
// consumption from the USB Vbus to <2.5mA* each. The USB module detects this condition (which according
// to the USB specifications is 3+ms of no bus activity/SOF packets) and then calls the USBCBSuspend()
// function. You should modify these callback functions to take appropriate actions for each of these
// conditions. For example, in the USBCBSuspend(), you may wish to add code that will decrease power
// consumption from Vbus to <2.5mA (such as by clock switching, turning off LEDs, putting the
// microcontroller to sleep, etc.). Then, in the USBCBWakeFromSuspend() function, you may then wish to
// add code that undoes the power saving things done in the USBCBSuspend() function.
//
// Note *: The "usb_20.pdf" specs indicate 500uA or 2.5mA, depending upon device classification. However,
// the USB-IF has officially issued an ECN (engineering change notice) changing this to 2.5mA for all
// devices. Make sure to re-download the latest specifications to get all of the newest ECNs.
/******************************************************************************
* Function: void USBCBWakeFromSuspend(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: The host may put USB peripheral devices in low power
* suspend mode (by "sending" 3+ms of idle). Once in suspend
* mode, the host may wake the device back up by sending non-
* idle state signalling.
*
* This call back is invoked when a wakeup from USB suspend
* is detected.
*
* Note: Before returning from this function, make sure that the
* oscillator settings are fully compatible with USB module
* operation.
* If using the two-speed startup feature, wakeup and execution
* will occur before the main oscillator + PLL has had a chance
* to start. Device will run from INTOSC (no PLL). However, the
* USB module cannot be clocked and receive correct USB data when
* it is not clocked with the correct frequency clock source.
* Therefore, when using two-speed startup, should execute software
* delay to prevent any other code from executing until the main
* oscillator is ready.
* The host will allow at least 10ms for USB "resume recovery", during
* which it will not try to communicate with the device.
*****************************************************************************/
void USBCBWakeFromSuspend(void)
{
//This code delays ~5ms @ 8MHz to execute (using C18 3.21 with full
//optimizations enabled), but takes much less time at 48MHz. This delay
//is to make sure the PLL is enabled and locked, in case two speed startup
//was enabled
DelayRoutine(0x300); //Device will switch clocks (if using two-speed startup) while executing this delay function
//Primary oscillator and PLL should be running by now.
//Do not return from this function until the oscillator is correctly configured and
//running in a USB compatible mode/frequency.
//Additional code for re-enabling I/O pins and increasing power draw from VBUS
//may be placed here (up to the maximum of 100mA [when unconfigured] or the
//amount specified in the configuration descriptor (when configured).
}
/******************************************************************************
* Function: void USBCBSuspend(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Call back that is invoked when a USB suspend is detected
*
* Note: None
*****************************************************************************/
void USBCBSuspend(void)
{
Sleep(); // Go to sleep, wake up when a USB activity event occurs
//If using the WDT, should go back to sleep if awoke by WDT instead of USBIF
while((USBIF_FLAG == 0) && (RCONbits.TO == 0)) //If using the WDT, should go back to sleep if awoke by WDT instead of USBIF
{
Sleep(); //Entry into sleep clears WDT count, much like executing ClrWdt() instruction
}
//After the USB suspend event ends, you should re-configure your I/O pins
//for normal operation mode (which is allowed to consume more current).
//However, it is recommended to put this code in the USBCBWakeFromSuspend()
//function instead of here (so that this function will work with either
//sleeping or clock switching to a lower frequency).
}
/*******************************************************************
* Function: void USBCBInitEP(uint8_t ConfigurationIndex)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function is called when the device becomes
* initialized, which occurs after the host sends a
* SET_CONFIGURATION request. This
* callback function should initialize the endpoints
* for the device's usage according to the current
* configuration.
*
* Note: If the host ever "unconfigures" the device, it will
* set the configuration to '0'. In this case, this
* callback gets called with ConfigurationIndex == 0, where
* the firmware should disable all non-EP0 endpoints (until
* the next non-zero SET_CONFIGURATION request is received,
* which will cause this callback to execute again).
*******************************************************************/
void USBCBInitEP(uint8_t ConfigurationIndex)
{
//Check what configuration "index" the host has requested us to select.
//Configuration index 0 is special and represents that the device should be
//un-configured. However, when the host sets the configuration (with index
//matching the valid/implemented configuration from the configuration descriptor),
//the firmware should enable the application endpoints associated with that
//configuration, and (re)initialize all application state variables associated
//with the USB application endpoints operation.
if(ConfigurationIndex == 1) //This application only implements one configuration, with index == 1.
{
//The host sent us a non-zero set configuration index. In this
//case we should prepare the application endpoints to be ready
//to use, and to (re-)initialize any application variables associated
//with the endpoints.
HIDInitEP();
//(Re-)Initialize the application variables associated with the USB interface
UserInit(); // See BootPIC[xxxx].c. Initializes the bootloader firmware state machine variables.
}
//else the host set the configuration back to 0 (indicating unconfigured), or
//to some higher (non-implemented value). In either case, we don't need to
//do anything specifically, unless the application requires some kind of
//"safe shutdown" code to execute after the host has deconfigured the device.
}
/*******************************************************************
* Function: void USBCBCheckOtherReq(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function is called when the USB stack receives a
* new control transfer SETUP packet from the host. The
* USB stack handles normal USB "Chapter 9" requests internally,
* but some control transfer requests are class specific. In
* order to handle these class specific requests, you must call
* the class handler's firmware control transfer handler function.
* If implementing a composite device with multiple classes
* implemented, call each of the handlers in the below callback.
*
* Note: None
*******************************************************************/
void USBCBCheckOtherReq(void)
{
USBCheckHIDRequest();
}