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