/******************************************************************************* * * * 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 //#include //#include 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