/******************************************************************************* * * * 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 "BootloaderInterface.h" #include "FlashMapping.h" #include //#include //#include unsigned int mSMState; unsigned int mPseudoTimer; extern unsigned long _app_start; int mIsSPIFlashDetected; void BootloaderSMInit(void) { mSMState = SM_CHECK_BOOTLOADER_FLAGS; mPseudoTimer = 0; mIsSPIFlashDetected = 0; } //#pragma CODE_SECTION(BootloaderSM,"ramfuncs"); void BootloaderSM(unsigned int event, unsigned int Data) { switch(mSMState) { case SM_STANDBY_STATE: { break; } case SM_CHECK_BOOTLOADER_FLAGS: { switch(event) { case SM_TICK_EVENT: { //First, check if SPI flash is functionnal if(mIsSPIFlashDetected == 0) { //Flash is not functionnal... //TODO: Check if we need to update via serial port // JumpToApp(); } //Flash is detected. Check the bootloader flags... BoootloaderGetBootloaderFlags(); // if(BootloaderAction == 0) // { // JumpToApp(); // } // else if(BootloaderAction == 1) // { // if( BootloaderAction == 0xA8) // { // //It's requested to write the firmware to PIC's Flash. Let's check SPI flash data integrity. // mSMState = SM_CHECK_FIRMWARE_VALIDITY; // } // else // { // //TODO: What should we do? // JumpToApp(); // } // } // else // { // //TODO // JumpToApp(); // } switch(mBootloaderFlags.BootloaderAction) { case BOOTLOADER_ACTION_JUMP_TO_APP_VALUE: { char mbuf[30]; mbuf[0] = 'G'; mbuf[1] = 'o'; mbuf[2] = 'i'; mbuf[3] = 'n'; mbuf[4] = 'g'; mbuf[5] = ' '; mbuf[6] = 'S'; mbuf[7] = 't'; mbuf[8] = 'd'; mbuf[9] = 'b'; mbuf[10] = 'y'; mbuf[11] = '\n'; mbuf[12] = '\r'; SendInternalUartData(&mbuf[0],13); mSMState = SM_STANDBY_STATE; JumpToApp(); break; } case BOOTLOADER_ACTION_FLASH_FIRMWARE_VALUE: { if( mBootloaderFlags.BootloaderActionValidator == BOOTLOADER_FLASH_FIRMWARE_VALIDATOR) { //It's requested to write the firmware to PIC's Flash. Let's check SPI flash data integrity. mSMState = SM_CHECK_FIRMWARE_VALIDITY; } else { //TODO: What should we do? JumpToApp(); } break; } case BOOTLOADER_ACTION_ENTER_UPDATE_MODE_VALUE: { //TODO JumpToApp(); break; } default: { JumpToApp(); break; } } // break; } case SM_RX_CMD_EVENT: case SM_ABORT_UPDATE: default: { break; } } break; } case SM_CHECK_FIRMWARE_VALIDITY: { switch(event) { case SM_TICK_EVENT: { if(BootloaderCheckFlashBootloaderData() == RET_OK) { //All is good, let's write the firmware to PIC's program Flash mSMState = SM_ERASE_INTERNAL_FLASH; } else { //TODO: What should we do? JumpToApp(); } break; } default: { break; } } break; } case SM_ERASE_INTERNAL_FLASH: { switch(event) { case SM_TICK_EVENT: { if(FlashErase() == FLASH_STATUS_ERROR) { char mbuf[30]; mbuf[0] = 'F'; mbuf[1] = 'l'; mbuf[2] = 'a'; mbuf[3] = 's'; mbuf[4] = 'h'; mbuf[5] = ' '; mbuf[6] = 'E'; mbuf[7] = 'r'; mbuf[8] = 'r'; mbuf[9] = 'o'; mbuf[10] = 'r'; mbuf[11] = '\n'; mbuf[12] = '\r'; SendInternalUartData(&mbuf[0],13); mSMState = SM_STANDBY_STATE; break; } else { // mSMState = SM_STANDBY_STATE; char mbuf[30]; mbuf[0] = 'F'; mbuf[1] = 'l'; mbuf[2] = 'a'; mbuf[3] = 's'; mbuf[4] = 'h'; mbuf[5] = ' '; mbuf[6] = 'E'; mbuf[7] = 'r'; mbuf[8] = 'a'; mbuf[9] = 's'; mbuf[10] = 'e'; mbuf[11] = 'd'; mbuf[12] = '\n'; mbuf[13] = '\r'; SendInternalUartData(&mbuf[0],14); mSMState = SM_WRITE_DATA_TO_PROGRAM_FLASH; } break; } default: { break; } } break; } case SM_WRITE_DATA_TO_PROGRAM_FLASH: { switch(event) { case SM_TICK_EVENT: { //First, load the firmware info. unsigned char FlashData[100]; unsigned int FlashAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS; unsigned int FileHeaderCode, FirmwareFlags, NbRecords, FirmwareSize, VersionCode, CRC32; // unsigned int ComputedCRC32 = CRC_START_32; //SPIFlashReadBuffer(FlashData,700,FlashAddress); //printf("Checking Flash bootloader data integrity... \n"); SPIFlashReadBuffer(FlashData,FLASH_BTLDR_HEADER_SIZE,FlashAddress); FileHeaderCode = BootloaderBytesToInt(FlashData); FirmwareFlags = BootloaderBytesToInt(&FlashData[4]); NbRecords = BootloaderBytesToInt(&FlashData[8]); FirmwareSize = BootloaderBytesToInt(&FlashData[12]); VersionCode = BootloaderBytesToInt(&FlashData[16]); CRC32 = BootloaderBytesToInt(&FlashData[20]); //TODO: Do we need to recheck validity? It's just been done before... FlashAddress += FLASH_BTLDR_HEADER_SIZE; //point to the start of bootloader data if(NbRecords > 0) { int CurRecord = 0; unsigned int Done = false; unsigned int RecHeader, RecSize, RecStartAddress; while(Done == false) { SPIFlashReadBuffer(&FlashData[0],12,FlashAddress); RecHeader = BootloaderBytesToInt(&FlashData[0]); RecSize = BootloaderBytesToInt(&FlashData[4]); //This is in bytes RecSize /= 4; RecStartAddress = BootloaderBytesToInt(&FlashData[8]); FlashAddress += 12; if(RecHeader != BOOTLOADER_RECORD_HEADER_CODE) { //TODO: What } // if(RecSize == 0) // { //TODO: What // return RET_ERROR; // } //Load the firmware data from SPI Flash CurrentDataSector.SectorStartAddress = RecStartAddress; CurrentDataSector.SectorSize = RecSize; int RecWord; for(RecWord = 0; RecWord < RecSize; RecWord++) { char WordBytes[4]; int Word; SPIFlashReadBuffer(WordBytes,4,FlashAddress); // Word = BootloaderBytesToInt(WordBytes); Word = BootloaderBytesToIntLittleEndian(WordBytes); CurrentDataSector.SectorData[RecWord] = Word; FlashAddress += 4; } //Write it to PIC's internal flash if(CurrentDataSector.SectorStartAddress < KVA_TO_PA(APPLICATION_FLASH_START_ADDRESS)) { //TODO: Manage this! } else if(FlashProgramData((void*)(CurrentDataSector.SectorStartAddress), CurrentDataSector.SectorData , CurrentDataSector.SectorSize) != FLASH_STATUS_OK) { //TODO: Manage this! char mbuf[30]; mbuf[0] = 'W'; mbuf[1] = 'r'; mbuf[2] = 'i'; mbuf[3] = 't'; mbuf[4] = 'e'; mbuf[5] = ' '; mbuf[6] = 'E'; mbuf[7] = 'r'; mbuf[8] = 'r'; mbuf[9] = 'o'; mbuf[10] = 'r'; mbuf[11] = '\n'; mbuf[12] = '\r'; SendInternalUartData(&mbuf[0],13); } CurRecord++; if(CurRecord == NbRecords) { Done = true; break; } } } //Fimware is all written successfully mSMState = SM_CHECK_PROGRAM_FLASH_VALIDITY; break; } default: { break; } // CurrentDataSector.SectorStartAddress break; } case SM_CHECK_PROGRAM_FLASH_VALIDITY: { switch(event) { case SM_TICK_EVENT: { //TODO: Compute CRC32... mSMState = SM_STANDBY_STATE; char mbuf[30]; mbuf[0] = 'F'; mbuf[1] = 'l'; mbuf[2] = 'a'; mbuf[3] = 's'; mbuf[4] = 'h'; mbuf[5] = ' '; mbuf[6] = 'P'; mbuf[7] = 'r'; mbuf[8] = 'o'; mbuf[9] = 'g'; mbuf[10] = 'r'; mbuf[11] = 'a'; mbuf[12] = 'm'; mbuf[13] = 'm'; mbuf[14] = 'e'; mbuf[15] = 'd'; mbuf[16] = '\n'; mbuf[17] = '\r'; SendInternalUartData(&mbuf[0],19); char toto[2]; toto[0] = 0; toto[1] = 0; SPIFlashWriteBuffer(toto,2,0x000000); JumpToApp(); } break; } default: { break; } } break; } case SM_ERROR_STATE: { // TODO: Manage this state break; } } } //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(); 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); void (*fptr)(void); fptr = (void (*)(void))APPLICATION_START_ADDRESS; fptr(); } void BootloaderSMSetSPIFlashDetected(int Detected) { mIsSPIFlashDetected = Detected; } void BootloaderSMReadBootloaderFlags() { } 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