BootloaderPIC32/Bootloader_PIC32.X/Source/BootloaderStateMachine.c
2020-11-16 05:47:46 -05:00

328 lines
7.3 KiB
C

/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*---- example include file ---------------------------------------------------*/
#include "define.h"
#include "BootloaderStateMachine.h"
#include "FlashInterface.h"
#include "BootloaderProtocol.h"
#include "InternalUart.h"
#include <plib.h>
//#include <string.h>
//#include <stdio.h>
unsigned int mSMState;
unsigned int mPseudoTimer;
extern unsigned long _app_start;
void BootloaderSMInit(void)
{
mSMState = SM_UPDATE_WAIT_STATE;
mPseudoTimer = 0;
}
#pragma CODE_SECTION(BootloaderSM,"ramfuncs");
void BootloaderSM(unsigned int event, unsigned int Data)
{
switch(mSMState)
{
case SM_UPDATE_WAIT_STATE:
{
switch(event)
{
case SM_TICK_EVENT:
{
if(mPseudoTimer++ >= PSEUDO_TIMER_VALUE)
{
char mbuf[30];
mbuf[0] = 'R';
mbuf[1] = 'e';
mbuf[2] = 'b';
mbuf[3] = 'o';
mbuf[4] = 'o';
mbuf[5] = 't';
mbuf[6] = 'i';
mbuf[7] = 'n';
mbuf[8] = 'g';
mbuf[9] = ' ';
mbuf[10] = 'i';
mbuf[11] = 'n';
mbuf[12] = ' ';
mbuf[13] = 'a';
mbuf[14] = 'p';
mbuf[15] = 'p';
mbuf[16] = '\r';
SendInternalUartData(&mbuf[0],17);
mPseudoTimer = 0;
// #ifndef _DEBUG
JumpToApp();
// #endif
}
break;
}
case SM_RX_CMD_EVENT:
{
if(Data == CONNECT_REQUEST_CMD)
{
mSMState = SM_IDLE_STATE;
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK); //Bootloader ack
}
//Ignore any other command received...
break;
}
case SM_ABORT_UPDATE:
{
break;
}
}
break; //case SM_UPDATE_WAIT_STATE:
}
case SM_IDLE_STATE:
{
switch(event)
{
case SM_TICK_EVENT:
{
break;
}
case SM_RX_CMD_EVENT:
{
switch(Data)
{
case START_UPDATE_REQUEST_CMD:
{
mSMState = SM_WAIT_FOR_UNLOCK_STATE;
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK); //Bootloader ack
break;
}
case HEARTBEAT_REQUEST_CMD:
{
ProtocolSendCmd(HEARTBEAT_CMD,0,0);
break;
}
case END_UPDATE_REQUEST_CMD:
{
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK); //Bootloader ack
SoftReset(); //simply reset cpu.
break;
}
case FLASH_API_VER_REQUEST_CMD:
{
char Version;
Version = 0x01;
ProtocolSendCmd(FLASH_API_VER_CMD,&Version,1);
break;
}
case SCRUB_FLASH_REQUEST_CMD:
{
//TODO
break;
}
}
break;
}
case SM_ABORT_UPDATE:
{
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK); //Bootloader ack
SoftReset();
break;
}
}
break; //case SM_IDLE_STATE:
}
case SM_WAIT_FOR_UNLOCK_STATE:
{
switch(event)
{
case SM_TICK_EVENT:
{
break;
}
case SM_RX_CMD_EVENT:
{
if(Data == BOOTLOADER_UNLOCK_REQUEST_CMD)
{
if(RxDataBuffer[0] == BOOTLOADER_UNLOCK_CODE)
{
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_FLASH_ERASE); //Inform PTE that flash is being erased
// #ifndef _DEBUG //don't touch FLASH in debug mode...
//Erase FLASH
if(FlashErase() != FLASH_STATUS_OK)
{
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_ERASE_FLASH_FAILED); //Acknowledge...
mSMState = SM_IDLE_STATE;
break;
}
// #endif
mSMState = SM_WAIT_FOR_NEXT_RECORD;
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK);
}
else//Invalid unlock code... return to IDLE...
{
mSMState = SM_IDLE_STATE;
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_INVALID_UNLOCK_CODE);
}
}
else//If another command than UNLOCK is received... return to IDLE
{
mSMState = SM_IDLE_STATE;
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_UNLOCK_EXPECTED);
}
break; //case SM_RX_CMD_EVENT
}
case SM_ABORT_UPDATE:
{
break;
}
}
break; //case SM_WAIT_FOR_UNLOCK_STATE:
}
case SM_WAIT_FOR_NEXT_RECORD:
{
switch(event)
{
case SM_TICK_EVENT:
{
break;
}
case SM_RX_CMD_EVENT:
{
switch(Data)
{
case SEND_RECORD_REQUEST_CMD:
{
//TODO: Address check...
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_FLASH_WRITE);
// unsigned int SectorStartAddress;
// unsigned short SectorSize;
// unsigned int *RecordDataPtr;
// unsigned int data;
//
// SectorStartAddress = *(unsigned int*)(&RxDataBuffer[0]);
// SectorSize = *(unsigned short*)(&RxDataBuffer[4]);
// RecordDataPtr = (unsigned int*)&RxDataBuffer[8];
// data = *RecordDataPtr;
// unsigned int test = KVA_TO_PA(APPLICATION_START_ADDRESS);
if(CurrentDataSector.SectorStartAddress < KVA_TO_PA(APPLICATION_FLASH_START_ADDRESS))
{
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_INVALID_ADDRESS);
break;
}
else if(FlashProgramData((void*)(CurrentDataSector.SectorStartAddress), CurrentDataSector.SectorData , CurrentDataSector.SectorSize) != FLASH_STATUS_OK)
{
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_WRITE_FLASH_FAILED);
break;
}
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK);
break;
}
case END_UPDATE_REQUEST_CMD:
{
ProtocolSendAck(PROTOCOL_ACK,RET_PROTOCOL_OK);
#ifndef _DEBUG
JumpToApp();
#else
mSMState = SM_IDLE_STATE;
#endif
break;
}
}
break; //case SM_RX_CMD_EVENT:
}
case SM_ABORT_UPDATE:
{
break;
}
}
break; //case SM_WAIT_FOR_NEXT_RECORD:
}
}
}
void JumpToApp()
{
// CloseInternalUart();
void (*fptr)(void);
fptr = (void (*)(void))APPLICATION_START_ADDRESS;
fptr();
}
void DownloadFlash(unsigned int StartAddress, unsigned int EndAddress)
{
/*
unsigned int CurAddress = StartAddress;
unsigned int Data;
unsigned int delay = 0;
char Buf[100];
int i = 0;
while(CurAddress < EndAddress)
{
Data = (CurAddress >> 16);
sprintf(Buf, "0x%.4X",Data);
SendInternalUartData(Buf,strlen(Buf));
// ProtocolSendCmd(FLASH_DATA_CMD,Buf,strlen(Buf));
Data = CurAddress;
sprintf(Buf, "%.4X ",Data);
SendInternalUartData(Buf,strlen(Buf));
// ProtocolSendCmd(FLASH_DATA_CMD,Buf,strlen(Buf));
for(i = 0; i < 16; i++)
{
Data = *(unsigned int*)CurAddress;
if(i != 15)
sprintf(Buf, "%.4X ",Data);
else
sprintf(Buf, "%.4X \r",Data);
SendInternalUartData(Buf,strlen(Buf));
// ProtocolSendCmd(FLASH_DATA_CMD,Buf,strlen(Buf));
CurAddress++;
// while(delay++ < 5000);
delay = 0;
}
}
e_FlashUpdateMode = false;
*/
}
//EOf