365 lines
7.9 KiB
C
365 lines
7.9 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 "BootloaderProtocol.h"
|
|
#include "BootloaderStateMachine.h"
|
|
#include "internaluart.h"
|
|
//#include <string.h>
|
|
|
|
|
|
enum eBootloaderProtocolStates ProtocolState;
|
|
unsigned int RxCounter;
|
|
unsigned int WordBuf;
|
|
unsigned short DataSize;
|
|
unsigned int CurCmd;
|
|
char *DataBufPtr;
|
|
char Checksum;
|
|
int ByteCount;
|
|
int *RecordDataPtr;
|
|
|
|
Bool e_CommandPending;
|
|
Bool e_FlashUpdateMode;
|
|
|
|
//#pragma DATA_ALIGN ( RxDataBuffer,16);
|
|
//#pragma DATA_SECTION(RxDataBuffer,"bootloaderbuffer");
|
|
unsigned char RxDataBuffer[MAX_RX_BUFF_SIZE]; //Rx buffer
|
|
|
|
//#pragma DATA_SECTION(TxBuffer,"bootloaderbuffer");
|
|
char TxBuffer[MAX_TX_BUFF_SIZE]; //Tx buffer
|
|
|
|
|
|
|
|
stDataSector_t CurrentDataSector;
|
|
|
|
|
|
void ProtocolInit(void)
|
|
{
|
|
ProtocolResetSM();
|
|
e_CommandPending = false;
|
|
e_FlashUpdateMode = false;
|
|
ByteCount = 0;
|
|
}
|
|
|
|
void ProtocolRxData( char mData )
|
|
{
|
|
|
|
if(e_CommandPending == true)
|
|
{
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_COMMAND_PENDING);
|
|
return;
|
|
}
|
|
|
|
if(e_FlashUpdateMode == true)
|
|
{
|
|
// DownloadFlash(0x328000, 0x32FFFF);
|
|
e_FlashUpdateMode = false;
|
|
return;
|
|
}
|
|
|
|
|
|
switch(ProtocolState)
|
|
{
|
|
case PROTOCOL_RX_HEADER:
|
|
{
|
|
if((unsigned char)mData == PROTOCOL_HEADER)
|
|
ProtocolState = PROTOCOL_RX_CMD;
|
|
|
|
break;
|
|
}
|
|
case PROTOCOL_RX_CMD:
|
|
{
|
|
CurCmd = ((unsigned int)mData & 0x00FF);
|
|
ProtocolState = PROTOCOL_RX_DATA_SIZE_1;
|
|
break;
|
|
}
|
|
case PROTOCOL_RX_DATA_SIZE_1:
|
|
{
|
|
DataSize = ((unsigned int)mData & 0x00FF); //((mData << 8) & 0xFF00);
|
|
ProtocolState = PROTOCOL_RX_DATA_SIZE_2;
|
|
break;
|
|
}
|
|
case PROTOCOL_RX_DATA_SIZE_2:
|
|
{
|
|
DataSize |= ((mData << 8) & 0xFF00); //(mData & 0x00FF);
|
|
if(DataSize > MAX_SECTOR_SIZE*4) //4 bytes per word...
|
|
{
|
|
ProtocolResetSM();
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_DATA_OVERSIZE);
|
|
}
|
|
else
|
|
{
|
|
if(DataSize == 0)
|
|
ProtocolState = PROTOCOL_RX_CHECKSUM;
|
|
else
|
|
{
|
|
if(CurCmd == SEND_RECORD_REQUEST_CMD && ((DataSize-6) % 4 != 0))// data must be 32 bits word) aligned when receiving a data record.
|
|
{
|
|
ProtocolResetSM();
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_DATA_BYTES_MISALIGNED);
|
|
break;
|
|
}
|
|
else
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE4;
|
|
//ProtocolState = PROTOCOL_RX_DATA_BYTE1;
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
/* case PROTOCOL_RX_DATA_BYTE1: //This compiler does not support 8 bits alignment
|
|
{
|
|
RxCounter++;
|
|
Checksum ^= mData;
|
|
|
|
if(CurCmd == SEND_RECORD_REQUEST_CMD) //for this command, we must concatenate 4 bytes in 1 word
|
|
{
|
|
WordBuf = (((unsigned int)mData << 24) & 0xFF000000);
|
|
|
|
if(RxCounter >= DataSize)
|
|
{
|
|
ProtocolResetSM();
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_DATA_BYTES_MISALIGNED);
|
|
}
|
|
else
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE2;
|
|
}
|
|
else
|
|
{
|
|
*DataBufPtr++ = mData; //Store new byte in buffer.
|
|
if(RxCounter >= DataSize) //all bytes received
|
|
{
|
|
ProtocolState = PROTOCOL_RX_CHECKSUM;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case PROTOCOL_RX_DATA_BYTE2:
|
|
{
|
|
WordBuf |= (((unsigned int)mData << 16) & 0x00FF0000);
|
|
RxCounter++;
|
|
|
|
*DataBufPtr++ = WordBuf; //Store new word in buffer.
|
|
Checksum ^= mData;
|
|
|
|
if(RxCounter >= DataSize)
|
|
{
|
|
ProtocolResetSM();
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_DATA_BYTES_MISALIGNED);
|
|
}
|
|
else
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE3;
|
|
}
|
|
case PROTOCOL_RX_DATA_BYTE3:
|
|
{
|
|
WordBuf |= (((unsigned int)mData << 8) & 0x0000FF00);
|
|
RxCounter++;
|
|
|
|
*DataBufPtr++ = WordBuf; //Store new word in buffer.
|
|
Checksum ^= mData;
|
|
|
|
if(RxCounter >= DataSize)
|
|
{
|
|
ProtocolResetSM();
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_DATA_BYTES_MISALIGNED);
|
|
}
|
|
else
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE4;
|
|
}
|
|
case PROTOCOL_RX_DATA_BYTE4:
|
|
{
|
|
WordBuf |= ((unsigned int)mData & 0x000000FF);
|
|
RxCounter++;
|
|
|
|
*DataBufPtr++ = WordBuf; //Store new word in buffer.
|
|
Checksum ^= mData;
|
|
|
|
if(RxCounter >= DataSize)
|
|
{
|
|
ProtocolState = PROTOCOL_RX_CHECKSUM; //all data received
|
|
}
|
|
else
|
|
{
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE1; //get next word
|
|
}
|
|
|
|
break;
|
|
}*/
|
|
|
|
case PROTOCOL_RX_DATA_BYTE4:
|
|
{
|
|
|
|
Checksum ^= mData;
|
|
*DataBufPtr++ = mData;
|
|
|
|
if(CurCmd == SEND_RECORD_REQUEST_CMD) //for this command, we must concatenate 4 bytes in 1 word
|
|
{
|
|
if(RxCounter == 3) //Start address..
|
|
{
|
|
CurrentDataSector.SectorStartAddress = *(unsigned int*)(&RxDataBuffer[0]);
|
|
DataBufPtr = &RxDataBuffer[0];
|
|
}
|
|
if(RxCounter == 5) //Record Size..
|
|
{
|
|
CurrentDataSector.SectorSize = *(unsigned short*)(&RxDataBuffer[0]);
|
|
DataBufPtr = &RxDataBuffer[0];
|
|
}
|
|
if(RxCounter > 5)
|
|
{
|
|
if(ByteCount == 3)
|
|
{
|
|
ByteCount = 0;
|
|
*RecordDataPtr++ = *(unsigned int*)(&RxDataBuffer[0]);
|
|
DataBufPtr = &RxDataBuffer[0];
|
|
|
|
}
|
|
else
|
|
{
|
|
ByteCount++;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
RxCounter++;
|
|
|
|
if(RxCounter >= DataSize)
|
|
{
|
|
ProtocolState = PROTOCOL_RX_CHECKSUM; //all data received
|
|
}
|
|
else
|
|
{
|
|
ProtocolState = PROTOCOL_RX_DATA_BYTE4; //get next word
|
|
}
|
|
|
|
break;
|
|
}
|
|
case PROTOCOL_RX_CHECKSUM:
|
|
{
|
|
if(mData == Checksum)
|
|
{
|
|
//execute command...
|
|
e_CommandPending = true;
|
|
// ProtocolExecCmd((enum eBootloaderProtocolCmds) CurCmd);
|
|
}
|
|
else
|
|
{
|
|
//Error, bad checksum...
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_BAD_CHECKSUM);
|
|
ProtocolResetSM();
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ProtocolResetSM();
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void ProtocolExecCmd()
|
|
{
|
|
switch(CurCmd)
|
|
{
|
|
case CONNECT_REQUEST_CMD: //Sent by the PTE in answer to BOOTLOADER_READY_CMD to enter boot mode
|
|
case BOOTLOADER_UNLOCK_REQUEST_CMD:
|
|
case HEARTBEAT_REQUEST_CMD:
|
|
case START_UPDATE_REQUEST_CMD:
|
|
case SEND_RECORD_REQUEST_CMD:
|
|
case END_UPDATE_REQUEST_CMD:
|
|
case FLASH_API_VER_REQUEST_CMD:
|
|
case SCRUB_FLASH_REQUEST_CMD:
|
|
{
|
|
BootloaderSM(SM_RX_CMD_EVENT,CurCmd);
|
|
break;
|
|
}
|
|
case FIRMWARE_RESET_REQUEST:
|
|
{
|
|
SoftReset();
|
|
break;
|
|
}
|
|
case DOWNLOAD_FLASH_REQUEST_CMD:
|
|
{
|
|
e_FlashUpdateMode = true;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ProtocolSendAck(PROTOCOL_NACK,RET_PROTOCOL_ERR_UNKNOWN_COMMAND);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ProtocolResetSM();
|
|
}
|
|
|
|
|
|
void ProtocolResetSM()
|
|
{
|
|
ProtocolState = PROTOCOL_RX_HEADER;
|
|
WordBuf = 0;
|
|
RxCounter = 0;
|
|
DataSize = 0;
|
|
CurCmd = 0;
|
|
DataBufPtr = &RxDataBuffer[0];
|
|
Checksum = 0;
|
|
RecordDataPtr = &CurrentDataSector.SectorData[0];
|
|
}
|
|
|
|
unsigned int ProtocolSendCmd(enum eBootloaderProtocolCmds mCmd, char *mData, unsigned mDataSize)
|
|
{
|
|
int i;
|
|
char mChecksum = 0;
|
|
if(mDataSize + 5 > MAX_TX_BUFF_SIZE)
|
|
return 0;
|
|
|
|
TxBuffer[0] = PROTOCOL_HEADER;
|
|
TxBuffer[1] = (char)mCmd;
|
|
TxBuffer[2] = LSB8(mDataSize);
|
|
TxBuffer[3] = MSB8(mDataSize);
|
|
|
|
for(i = 0; i < mDataSize; i++)
|
|
{
|
|
mChecksum ^= *mData;
|
|
TxBuffer[i+4] = *mData++;
|
|
}
|
|
|
|
|
|
TxBuffer[mDataSize + 4] = mChecksum;
|
|
|
|
|
|
SendInternalUartData(TxBuffer,mDataSize+5);
|
|
|
|
return mDataSize + 5;
|
|
|
|
|
|
}
|
|
|
|
void ProtocolSendAck(enum eBootloaderAcknowledgement mAck, enum eBootloaderProtocolRet mErr)
|
|
{
|
|
char mAckBufferData[2];
|
|
mAckBufferData[0] = (char) mAck;
|
|
mAckBufferData[1] = (char) mErr;
|
|
|
|
ProtocolSendCmd(ACKNOWLEDGE_CMD, mAckBufferData, 2);
|
|
}
|
|
|
|
|
|
|