BootloaderPIC32/Bootloader_PIC32.X/Source/BootloaderStateMachine.c

724 lines
17 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 "BootloaderInterface.h"
#include "FlashMapping.h"
#include <plib.h>
//#include <string.h>
//#include <stdio.h>
unsigned int mSMState;
unsigned int mPseudoTimer;
extern unsigned long _app_start;
int mIsSPIFlashDetected;
void BootloaderSMInit(void)
{
mSMState = SM_CHECK_BOOTLOADER_FLAGS;
mPseudoTimer = 0;
mIsSPIFlashDetected = 0;
}
//#pragma CODE_SECTION(BootloaderSM,"ramfuncs");
void BootloaderSM(unsigned int event, unsigned int Data)
{
switch(mSMState)
{
case SM_STANDBY_STATE:
{
break;
}
case SM_CHECK_BOOTLOADER_FLAGS:
{
switch(event)
{
case SM_TICK_EVENT:
{
//First, check if SPI flash is functionnal
if(mIsSPIFlashDetected == 0)
{
//Flash is not functionnal...
//TODO: Check if we need to update via serial port
// JumpToApp();
}
//Flash is detected. Check the bootloader flags...
BoootloaderGetBootloaderFlags();
// if(BootloaderAction == 0)
// {
// JumpToApp();
// }
// else if(BootloaderAction == 1)
// {
// if( BootloaderAction == 0xA8)
// {
// //It's requested to write the firmware to PIC's Flash. Let's check SPI flash data integrity.
// mSMState = SM_CHECK_FIRMWARE_VALIDITY;
// }
// else
// {
// //TODO: What should we do?
// JumpToApp();
// }
// }
// else
// {
// //TODO
// JumpToApp();
// }
switch(mBootloaderFlags.BootloaderAction)
{
case BOOTLOADER_ACTION_JUMP_TO_APP_VALUE:
{
char mbuf[30];
mbuf[0] = 'G';
mbuf[1] = 'o';
mbuf[2] = 'i';
mbuf[3] = 'n';
mbuf[4] = 'g';
mbuf[5] = ' ';
mbuf[6] = 'S';
mbuf[7] = 't';
mbuf[8] = 'd';
mbuf[9] = 'b';
mbuf[10] = 'y';
mbuf[11] = '\n';
mbuf[12] = '\r';
SendInternalUartData(&mbuf[0],13);
mSMState = SM_STANDBY_STATE;
JumpToApp();
break;
}
case BOOTLOADER_ACTION_FLASH_FIRMWARE_VALUE:
{
if( mBootloaderFlags.BootloaderActionValidator == BOOTLOADER_FLASH_FIRMWARE_VALIDATOR)
{
//It's requested to write the firmware to PIC's Flash. Let's check SPI flash data integrity.
mSMState = SM_CHECK_FIRMWARE_VALIDITY;
}
else
{
//TODO: What should we do?
JumpToApp();
}
break;
}
case BOOTLOADER_ACTION_ENTER_UPDATE_MODE_VALUE:
{
//TODO
JumpToApp();
break;
}
default:
{
JumpToApp();
break;
}
}
//
break;
}
case SM_RX_CMD_EVENT:
case SM_ABORT_UPDATE:
default:
{
break;
}
}
break;
}
case SM_CHECK_FIRMWARE_VALIDITY:
{
switch(event)
{
case SM_TICK_EVENT:
{
if(BootloaderCheckFlashBootloaderData() == RET_OK)
{
//All is good, let's write the firmware to PIC's program Flash
mSMState = SM_ERASE_INTERNAL_FLASH;
}
else
{
//TODO: What should we do?
JumpToApp();
}
break;
}
default:
{
break;
}
}
break;
}
case SM_ERASE_INTERNAL_FLASH:
{
switch(event)
{
case SM_TICK_EVENT:
{
if(FlashErase() == FLASH_STATUS_ERROR)
{
char mbuf[30];
mbuf[0] = 'F';
mbuf[1] = 'l';
mbuf[2] = 'a';
mbuf[3] = 's';
mbuf[4] = 'h';
mbuf[5] = ' ';
mbuf[6] = 'E';
mbuf[7] = 'r';
mbuf[8] = 'r';
mbuf[9] = 'o';
mbuf[10] = 'r';
mbuf[11] = '\n';
mbuf[12] = '\r';
SendInternalUartData(&mbuf[0],13);
mSMState = SM_STANDBY_STATE;
break;
}
else
{
// mSMState = SM_STANDBY_STATE;
char mbuf[30];
mbuf[0] = 'F';
mbuf[1] = 'l';
mbuf[2] = 'a';
mbuf[3] = 's';
mbuf[4] = 'h';
mbuf[5] = ' ';
mbuf[6] = 'E';
mbuf[7] = 'r';
mbuf[8] = 'a';
mbuf[9] = 's';
mbuf[10] = 'e';
mbuf[11] = 'd';
mbuf[12] = '\n';
mbuf[13] = '\r';
SendInternalUartData(&mbuf[0],14);
mSMState = SM_WRITE_DATA_TO_PROGRAM_FLASH;
}
break;
}
default:
{
break;
}
}
break;
}
case SM_WRITE_DATA_TO_PROGRAM_FLASH:
{
switch(event)
{
case SM_TICK_EVENT:
{
//First, load the firmware info.
unsigned char FlashData[100];
unsigned int FlashAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS;
unsigned int FileHeaderCode, FirmwareFlags, NbRecords, FirmwareSize, VersionCode, CRC32;
// unsigned int ComputedCRC32 = CRC_START_32;
//SPIFlashReadBuffer(FlashData,700,FlashAddress);
//printf("Checking Flash bootloader data integrity... \n");
SPIFlashReadBuffer(FlashData,FLASH_BTLDR_HEADER_SIZE,FlashAddress);
FileHeaderCode = BootloaderBytesToInt(FlashData);
FirmwareFlags = BootloaderBytesToInt(&FlashData[4]);
NbRecords = BootloaderBytesToInt(&FlashData[8]);
FirmwareSize = BootloaderBytesToInt(&FlashData[12]);
VersionCode = BootloaderBytesToInt(&FlashData[16]);
CRC32 = BootloaderBytesToInt(&FlashData[20]);
//TODO: Do we need to recheck validity? It's just been done before...
FlashAddress += FLASH_BTLDR_HEADER_SIZE; //point to the start of bootloader data
if(NbRecords > 0)
{
int CurRecord = 0;
unsigned int Done = false;
unsigned int RecHeader, RecSize, RecStartAddress;
while(Done == false)
{
SPIFlashReadBuffer(&FlashData[0],12,FlashAddress);
RecHeader = BootloaderBytesToInt(&FlashData[0]);
RecSize = BootloaderBytesToInt(&FlashData[4]); //This is in bytes
RecSize /= 4;
RecStartAddress = BootloaderBytesToInt(&FlashData[8]);
FlashAddress += 12;
if(RecHeader != BOOTLOADER_RECORD_HEADER_CODE)
{
//TODO: What
}
// if(RecSize == 0)
// {
//TODO: What
// return RET_ERROR;
// }
//Load the firmware data from SPI Flash
CurrentDataSector.SectorStartAddress = RecStartAddress;
CurrentDataSector.SectorSize = RecSize;
int RecWord;
for(RecWord = 0; RecWord < RecSize; RecWord++)
{
char WordBytes[4];
int Word;
SPIFlashReadBuffer(WordBytes,4,FlashAddress);
// Word = BootloaderBytesToInt(WordBytes);
Word = BootloaderBytesToIntLittleEndian(WordBytes);
CurrentDataSector.SectorData[RecWord] = Word;
FlashAddress += 4;
}
//Write it to PIC's internal flash
if(CurrentDataSector.SectorStartAddress < KVA_TO_PA(APPLICATION_FLASH_START_ADDRESS))
{
//TODO: Manage this!
}
else if(FlashProgramData((void*)(CurrentDataSector.SectorStartAddress), CurrentDataSector.SectorData , CurrentDataSector.SectorSize) != FLASH_STATUS_OK)
{
//TODO: Manage this!
char mbuf[30];
mbuf[0] = 'W';
mbuf[1] = 'r';
mbuf[2] = 'i';
mbuf[3] = 't';
mbuf[4] = 'e';
mbuf[5] = ' ';
mbuf[6] = 'E';
mbuf[7] = 'r';
mbuf[8] = 'r';
mbuf[9] = 'o';
mbuf[10] = 'r';
mbuf[11] = '\n';
mbuf[12] = '\r';
SendInternalUartData(&mbuf[0],13);
}
CurRecord++;
if(CurRecord == NbRecords)
{
Done = true;
break;
}
}
}
//Fimware is all written successfully
mSMState = SM_CHECK_PROGRAM_FLASH_VALIDITY;
break;
}
default:
{
break;
}
// CurrentDataSector.SectorStartAddress
break;
}
case SM_CHECK_PROGRAM_FLASH_VALIDITY:
{
switch(event)
{
case SM_TICK_EVENT:
{
//TODO: Compute CRC32...
mSMState = SM_STANDBY_STATE;
char mbuf[30];
mbuf[0] = 'F';
mbuf[1] = 'l';
mbuf[2] = 'a';
mbuf[3] = 's';
mbuf[4] = 'h';
mbuf[5] = ' ';
mbuf[6] = 'P';
mbuf[7] = 'r';
mbuf[8] = 'o';
mbuf[9] = 'g';
mbuf[10] = 'r';
mbuf[11] = 'a';
mbuf[12] = 'm';
mbuf[13] = 'm';
mbuf[14] = 'e';
mbuf[15] = 'd';
mbuf[16] = '\n';
mbuf[17] = '\r';
SendInternalUartData(&mbuf[0],19);
char toto[2];
toto[0] = 0;
toto[1] = 0;
SPIFlashWriteBuffer(toto,2,0x000000);
JumpToApp();
}
break;
}
default:
{
break;
}
}
break;
}
case SM_ERROR_STATE:
{
// TODO: Manage this state
break;
}
}
}
//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();
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);
void (*fptr)(void);
fptr = (void (*)(void))APPLICATION_START_ADDRESS;
fptr();
}
void BootloaderSMSetSPIFlashDetected(int Detected)
{
mIsSPIFlashDetected = Detected;
}
void BootloaderSMReadBootloaderFlags()
{
}
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