/********************************************************************
* 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)
}
Пример #2
0
/********************************************************************
* 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()
Пример #3
0
/********************************************************************
* 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)