328 lines
7.3 KiB
C
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
|
|
|
|
|