📄 boot.c
字号:
/********************************************************************
*
* PIC24F Serial Bootloader
*
*********************************************************************
* FileName: boot.c
* Dependencies: memory.c, config.h, GenericTypeDefs.h
* Processor: PIC24F Family
* Compiler: C30 v3.00 or later
* Company: Microchip Technology, Inc.
*
* Software License Agreement:
*
* The software supplied herewith by Microchip Technology Incorporated
* (the 揅ompany? for its PICmicro?Microcontroller is intended and
* supplied to you, the Company抯 customer, for use solely and
* exclusively on Microchip PICmicro Microcontroller products. The
* software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN 揂S IS?CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FrOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*
* File Description:
*
* Bootloader for PIC24F devices compatable with AN851 communication protocol
* Based on PIC24F UART bootloader and PIC16/18 AN851 bootloader
*
*
* Change History:
*
* Author Revision # Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Brant Ivey 1.00 1-17-2008 Initial release of AN1157
* Brant Ivey 1.02 11-17-2008 Updated 'K' device support
* Added extra configuration options
********************************************************************/
//Includes *******************************
#include "PIC24F Serial Bootloader\config.h"
//****************************************
//Globals ********************************
WORD responseBytes; //number of bytes in command response
DWORD_VAL sourceAddr; //general purpose address variable
DWORD_VAL userReset; //user code reset vector
DWORD_VAL userTimeout; //bootloader entry timeout value
WORD userResetRead; //bool - for relocating user reset vector
//Variables for storing runaway code protection keys
#ifdef USE_RUNAWAY_PROTECT
volatile WORD writeKey1 = 0xFFFF;
volatile WORD writeKey2 = 0x5555;
volatile WORD keyTest1 = 0x0000;
volatile WORD keyTest2 = 0xAAAA;
#endif
#define CLR_DT PORTBbits.RB12=0
#define SET_DT PORTBbits.RB12=1
//Transmit/Recieve Buffer
BYTE buffer[MAX_PACKET_SIZE+1];
//****************************************
//Configuration bits *********************
_CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_ON& ICS_PGx2);
_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_HS & FNOSC_PRIPLL & I2C1SEL_PRI& IOL1WAY_OFF);
//****************************************
/********************************************************************
* Function: int main()
*
* Precondition: None.
*
* Input: None.
*
* Output: None.
*
* Side Effects: Enables 32-bit Timer2/3. Enables UART.
*
* Overview: Initialization of program and main loop.
*
* Note: None.
********************************************************************/
unsigned num,subnum;
int main()
{
DWORD_VAL delay;
//Setup bootloader entry delay
sourceAddr.Val = DELAY_TIME_ADDR; //bootloader timer address
delay.Val = ReadLatch(sourceAddr.word.HW, sourceAddr.word.LW); //read BL timeout
//Setup user reset vector
sourceAddr.Val = USER_PROG_RESET;
userReset.Val = ReadLatch(sourceAddr.word.HW, sourceAddr.word.LW);
//Prevent bootloader lockout - if no user reset vector, reset to BL start
if(userReset.Val == 0xFFFFFF){
userReset.Val = BOOT_ADDR_LOW;
}
userResetRead = 0;
//If timeout is zero, check reset state.
if(delay.v[0] == 0){
//If device is returning from reset, BL is disabled call user code
//otherwise assume the BL was called from use code and enter BL
if(RCON & 0xFED3){
//If bootloader disabled, go to user code
ResetDevice(userReset.Val);
}else{
delay.Val = 0xFF;
}
}
T2CONbits.TON = 0;
T2CONbits.T32 = 1; // Setup Timer 2/3 as 32 bit timer incrementing every clock
IFS0bits.T3IF = 0; // Clear the Timer3 Interrupt Flag
IEC0bits.T3IE = 0; // Disable Timer3 Interrupt Service Routine
//Enable timer if not in always-BL mode
if((delay.Val & 0x000000FF) != 0xFF){
//Convert seconds into timer count value
delay.Val = ((DWORD)(FCY)) * ((DWORD)(delay.v[0]));
PR3 = delay.word.HW; //setup timer timeout value
PR2 = delay.word.LW;
TMR2 = 0;
TMR3 = 0;
T2CONbits.TON=1; //enable timer
}
TRISBbits.TRISB6=0;
TRISBbits.TRISB7=1;
TRISBbits.TRISB12=0;
// asm volatile("MOV #OSCCON, w1 \n"
// "MOV #0x46, w2 \n"
// "MOV #0x57, w3 \n"
// "MOV.b w2, [w1] \n"
// "MOV.b w3, [w1] \n"
// "BCLR OSCCON, #6");
RPINR18bits.U1RXR=7;
RPOR3bits.RP6R=3;
// asm volatile("MOV #OSCCON, w1 \n"
// "MOV #0x46, w2 \n"
// "MOV #0x57, w3 \n"
// "MOV.b w2, [w1] \n"
// "MOV.b w3, [w1] \n"
// "BSET OSCCON, #6");
U1BRG = ((FCY/9600)/16)-1 ; /* BAUD Rate Setting of Uart1 */
U1MODE = 0x8000; /* Reset UART to 8-n-1, alt pins, and enable */
U1STA = 0x0400; /* Reset status register and enable TX */
//TRISAbits.TRISA4=0;
//PORTAbits.RA4=0;
CLR_DT;
while(1){
#ifdef USE_RUNAWAY_PROTECT
writeKey1 = 0xFFFF; // Modify keys to ensure proper program flow
writeKey2 = 0x5555;
#endif
GetCommand(); //Get full AN851 command from UART
#ifdef USE_RUNAWAY_PROTECT
writeKey1 += 10; // Modify keys to ensure proper program flow
writeKey2 += 42;
#endif
HandleCommand(); //Handle the command
PutResponse(responseBytes); //Respond to sent command
}//end while(1)
}//end main(void)
/********************************************************************
* Function: void GetCommand()
*
* Precondition: UART Setup
*
* Input: None.
*
* Output: None.
*
* Side Effects: None.
*
* Overview: Polls the UART to recieve a complete AN851 command.
* Fills buffer[1024] with recieved data.
*
* Note: None.
********************************************************************/
void GetCommand(){
BYTE RXByte;
BYTE checksum;
WORD dataCount;
while(1){
#ifndef USE_AUTOBAUD
GetChar(&RXByte); //Get first STX
if(RXByte == STX){
#else
AutoBaud(); //Get first STX and calculate baud rate
RXByte = U1RXREG; //Dummy read
#endif
T2CONbits.TON = 0; //disable timer - data received
GetChar(&RXByte); //Read second byte
if(RXByte == STX){ //2 STX, beginning of data
checksum = 0; //reset data and checksum
dataCount = 0;
while(dataCount <= MAX_PACKET_SIZE+1){ //maximum num bytes
GetChar(&RXByte);
switch(RXByte){
case STX: //Start over if STX
checksum = 0;
dataCount = 0;
break;
case ETX: //End of packet if ETX
checksum = ~checksum +1; //test checksum
Nop();
if(checksum == 0) return; //return if OK
dataCount = 0xFFFF; //otherwise restart
break;
case DLE: //If DLE, treat next as data
GetChar(&RXByte);
default: //get data, put in buffer
checksum += RXByte;
buffer[dataCount++] = RXByte;
break;
}//end switch(RXByte)
}//end while(byteCount <= 1024)
}//end if(RXByte == STX)
#ifndef USE_AUTOBAUD
}//end if(RXByte == STX)
#endif
}//end while(1)
}//end GetCommand()
/********************************************************************
* Function: void HandleCommand()
*
* Precondition: data in buffer
*
* Input: None.
*
* Output: None.
*
* Side Effects: None.
*
* Overview: Handles commands received from host
*
* Note: None.
********************************************************************/
void HandleCommand()
{
BYTE Command;
BYTE length;
//variables used in EE and CONFIG read/writes
#if (defined(DEV_HAS_EEPROM) || defined(DEV_HAS_CONFIG_BITS))
WORD i=0;
WORD_VAL temp;
WORD bytesRead = 0;
#endif
Command = buffer[0]; //get command from buffer
length = buffer[1]; //get data length from buffer
//RESET Command
if(length == 0x00){
UxMODEbits.UARTEN = 0; //Disable UART
ResetDevice(userReset.Val);
}
//get 24-bit address from buffer
sourceAddr.v[0] = buffer[2];
sourceAddr.v[1] = buffer[3];
sourceAddr.v[2] = buffer[4];
sourceAddr.v[3] = 0;
#ifdef USE_RUNAWAY_PROTECT
writeKey1 |= (WORD)sourceAddr.Val; // Modify keys to ensure proper program flow
writeKey2 = writeKey2 << 1;
#endif
//Handle Commands
switch(Command)
{
case RD_VER: //Read version
buffer[2] = MINOR_VERSION;
buffer[3] = MAJOR_VERSION;
responseBytes = 4; //set length of reply
break;
case RD_FLASH: //Read flash memory
ReadPM(length, sourceAddr);
responseBytes = length*PM_INSTR_SIZE + 5; //set length of reply
break;
case WT_FLASH: //Write flash memory
#ifdef USE_RUNAWAY_PROTECT
writeKey1 -= length; // Modify keys to ensure proper program flow
writeKey2 += Command;
#endif
WritePM(length, sourceAddr);
responseBytes = 1; //set length of reply
break;
case ER_FLASH: //Erase flash memory
#ifdef USE_RUNAWAY_PROTECT
writeKey1 += length; // Modify keys to ensure proper program flow
writeKey2 -= Command;
#endif
ErasePM(length, sourceAddr);
responseBytes = 1; //set length of reply
break;
#ifdef DEV_HAS_EEPROM
case RD_EEDATA: //Read EEPROM
//if device has onboard EEPROM, allow EE reads
//Read length words of EEPROM
while(i < length*2){
temp.Val = ReadLatch(sourceAddr.word.HW,
sourceAddr.word.LW);
buffer[5+i++] = temp.v[0];
buffer[5+i++] = temp.v[1];
sourceAddr.Val += 2;
}
responseBytes = length*2 + 5; //set length of reply
break;
case WT_EEDATA: //Write EEPROM
#ifdef USE_RUNAWAY_PROTECT
writeKey1 -= length; // Modify keys to ensure proper program flow
writeKey2 += Command;
#endif
//Write length words of EEPROM
while(i < length*2){
temp.byte.LB = buffer[5+i++]; //load data to write
temp.byte.HB = buffer[5+i++];
WriteLatch(sourceAddr.word.HW,sourceAddr.word.LW,
0, temp.Val); //write data to latch
#ifdef USE_RUNAWAY_PROTECT
writeKey1++;
writeKey2--;
//setup program flow protection test keys
keyTest1 = (((0x0009 | (WORD)(sourceAddr.Val-i)) -
length) + i/2) - 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -