2020-11-16 05:47:46 -05:00

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);
}