/******************************************************************** * Function: void ReadPM(WORD length, DWORD_VAL sourceAddr) * * PreCondition: None * * Input: length - number of instructions to read * sourceAddr - address to read from * * Output: None * * Side Effects: Puts read instructions into buffer. * * Overview: Reads from program memory, stores data into buffer. * * Note: None ********************************************************************/ void ReadPM(WORD length, DWORD_VAL sourceAddr) { WORD bytesRead = 0; DWORD_VAL temp; while(bytesRead < length*PM_INSTR_SIZE) { //Read length instructions from flash temp.Val = ReadLatch(sourceAddr.word.HW, sourceAddr.word.LW); //Read flash buffer[bytesRead+5] = temp.v[0]; //Put read data onto buffer[bytesRead+6] = temp.v[1]; //Response buffer buffer[bytesRead+7] = temp.v[2]; buffer[bytesRead+8] = temp.v[3]; bytesRead+=PM_INSTR_SIZE; //4 bytes per instruction: low word, high byte, phantom byte sourceAddr.Val = sourceAddr.Val + 2; //Increment addr by 2 } //End while(bytesRead < length*PM_INSTR_SIZE) }
/******************************************************************** * 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; keyTest2 = (((0x557F << 1) + WT_EEDATA) - i/2) + 6; //initiate write sequence WriteMem(EE_WORD_WRITE); writeKey1 += 5; // Modify keys to ensure proper program flow writeKey2 -= 6; #else //initiate write sequence bypasssing runaway protection WriteMem(EE_WORD_WRITE); #endif sourceAddr.Val +=2; } responseBytes = 1; //set length of reply break; #endif #ifdef DEV_HAS_CONFIG_BITS case RD_CONFIG: //Read config memory //Read length bytes from config memory while(bytesRead < length) { //read flash temp.Val = ReadLatch(sourceAddr.word.HW, sourceAddr.word.LW); buffer[bytesRead+5] = temp.v[0]; //put read data onto buffer bytesRead++; sourceAddr.Val += 2; //increment addr by 2 } responseBytes = length + 5; break; case WT_CONFIG: //Write Config mem //Write length bytes of config memory while(i < length){ temp.byte.LB = buffer[5+i++]; //load data to write temp.byte.HB = 0; #ifdef USE_RUNAWAY_PROTECT writeKey1++; writeKey2--; #endif //Make sure that config write is inside implemented configuration space if(sourceAddr.Val >= CONFIG_START && sourceAddr.Val <= CONFIG_END) { TBLPAG = sourceAddr.byte.UB; __builtin_tblwtl(sourceAddr.word.LW,temp.Val); #ifdef USE_RUNAWAY_PROTECT //setup program flow protection test keys keyTest1 = (((0x0009 | (WORD)(sourceAddr.Val-i*2)) - length) + i) - 5; keyTest2 = (((0x557F << 1) + WT_CONFIG) - i) + 6; //initiate write sequence WriteMem(CONFIG_WORD_WRITE); writeKey1 += 5; // Modify keys to ensure proper program flow writeKey2 -= 6; #else //initiate write sequence bypasssing runaway protection WriteMem(CONFIG_WORD_WRITE); #endif }//end if(sourceAddr.Val...) sourceAddr.Val +=2; }//end while(i < length) responseBytes = 1; //set length of reply break; #endif case VERIFY_OK: #ifdef USE_RUNAWAY_PROTECT writeKey1 -= 1; // Modify keys to ensure proper program flow writeKey2 += Command; #endif WriteTimeout(); responseBytes = 1; //set length of reply break; default: break; }// end switch(Command) }//end HandleCommand()
/******************************************************************** * 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. ********************************************************************/ 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 } //If using a part with PPS, map the UART I/O #ifdef DEV_HAS_PPS ioMap(); #endif //Configure UART pins to be digital I/O. #ifdef UTX_ANA UTX_ANA = 1; #endif #ifdef URX_ANA URX_ANA = 1; #endif // SETUP UART COMMS: No parity, one stop bit, autobaud, polled UxMODEbits.UARTEN = 1; //enable uart #ifdef USE_AUTOBAUD UxMODEbits.ABAUD = 1; //use autobaud #else UxBRG = BAUDRATEREG; #endif #ifdef USE_HI_SPEED_BRG UxMODEbits.BRGH = 1; //use high speed mode #endif UxSTA = 0x0400; //Enable TX 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)