Index: firmware/App/Common.h =================================================================== diff -u -r621896c8a4cc9204a12a7243ccef729c37e50c52 -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Common.h (.../Common.h) (revision 621896c8a4cc9204a12a7243ccef729c37e50c52) +++ firmware/App/Common.h (.../Common.h) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -64,6 +64,8 @@ STANDBY_CHECK_FOR_UPDATE_STATE = 0, ///< Standby check for update state. STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE, ///< Standby check firmware and FPGA images state. STANDBY_IDLE_STATE, ///< Standby idle state. + STANDBY_CHECK_UPDATED_IMAGE_STATE, ///< Standby check updated image state. + STANDBY_RESET_BOOTLOADER_STATE, ///< Standby reset bootloader state. NUM_OF_MODE_STANDBY_STATES ///< Number of standby states. } MODE_STANDBY_STATE_T; @@ -156,6 +158,15 @@ { SW_UPDATE_DD_UPDATE, SW_UPDATE_DD_RESP }, ///< Software update DD. }; +/// Software update response status structure +typedef struct +{ + U16 msgID; ///< Message ID. + U08 msgAckNackStatus; ///< Message ack or nack status. + U08 spareSpace; ///< Message spare byte. + U32 msgCRC; ///< Message CRC. +} SW_UPDATE_RESP_STATUS_T; + /**@}*/ #endif Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r2823873d5790228595fb991e52e78e2fd0d5987c -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -1,6 +1,7 @@ #include // For memcpy and memset +#include "reg_system.h" #include "sys_core.h" // To disable RAM and Flash ECC #include "sys_mpu.h" // To disable MPU @@ -9,6 +10,7 @@ #include "ModeStandby.h" #include "NVDataMgmt.h" #include "OperationModes.h" +#include "SystemComm.h" #include "Timers.h" #include "Utilities.h" @@ -19,7 +21,7 @@ // ********** private definitions ********** -#define WAIT_FOR_UPDATE_FROM_UI_MS 2000 ///< Wait for update timeout in milliseconds. +#define WAIT_FOR_UPDATE_FROM_UI_MS 1000 ///< Wait for update timeout in milliseconds. // ********** private data ********** @@ -28,10 +30,13 @@ // ********** private function prototypes ********** static MODE_STANDBY_STATE_T handleStandbyModeCheckForUpdateState( void ); -static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImages( void ); +static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImagesState( void ); static MODE_STANDBY_STATE_T handleStandbyModeIdleState( void ); +static MODE_STANDBY_STATE_T handleStandbyModeCheckUpdatedImageStates( void ); +static MODE_STANDBY_STATE_T handleStandyModeResetBootloaderState( void ); static void jumpToApplication( void ); +static void resetBootloader( void ); /*********************************************************************//** * @brief @@ -81,13 +86,21 @@ break; case STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE: - standbyCurrentState = handleStandbyModeCheckFWAndFPGAImages(); + standbyCurrentState = handleStandbyModeCheckFWAndFPGAImagesState(); break; case STANDBY_IDLE_STATE: standbyCurrentState = handleStandbyModeIdleState(); break; + case STANDBY_CHECK_UPDATED_IMAGE_STATE: + standbyCurrentState = handleStandbyModeCheckUpdatedImageStates(); + break; + + case STANDBY_RESET_BOOTLOADER_STATE: + standbyCurrentState = handleStandyModeResetBootloaderState(); + break; + default: // Do nothing break; @@ -119,50 +132,54 @@ break; case UPDATE_CMD_VERIFY: - state = STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE; + state = STANDBY_CHECK_UPDATED_IMAGE_STATE; break; + case UPDATE_CMD_IDLE: + if ( TRUE == didTimeout( getLastBroadcastMessageTimeStampMS(), WAIT_FOR_UPDATE_FROM_UI_MS ) ) + { + state = STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE; + } + break; + default: // Do nothing break; } - if ( TRUE == didTimeout( getLastBroadcastMessageTimeStampMS(), WAIT_FOR_UPDATE_FROM_UI_MS ) ) - { - state = STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE; - } - return state; } /*********************************************************************//** * @brief - * The handleStandbyModeCheckFWAndFPGAImages function handles the standby + * The handleStandbyModeCheckFWAndFPGAImagesState function handles the standby * check firmware and FPGA images state. * This state checks the integrity of the firmware as well as the FPGA header * to make sure the images are valid. * @details \b Inputs: none * @details \b Outputs: none * @return next state of the standby mode state machine *************************************************************************/ -static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImages( void ) +static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImagesState( void ) { MODE_STANDBY_STATE_T state = STANDBY_IDLE_STATE; BOOL isFirmwareImageValid = FALSE; BOOL isFPGAImageValid = FALSE; + SW_UPDATE_CMD_T cmd = getSWUpdateCommandState(); + // TODO why a bad code passes the CRC? - // TODO send the results back (pass/fail) up to be sent to the cloud. if ( TRUE == isFWCRCTableValid() ) { isFirmwareImageValid = runFWIntegrityTest(); } - if ( TRUE == isFPGAIDValid() ) // TODO change the FPGA ID to Leahi. It is not right now to not jump + if ( TRUE == isFPGAIDValid() ) { isFPGAImageValid = TRUE; } // NOTE: If either of the images (firmware or FPGA) failed, go to the idle state until another update request is received + // If both images are good and no update was in progress, jump to firmware address if ( ( TRUE == isFirmwareImageValid ) && ( TRUE == isFPGAImageValid ) ) { // All good, jump to application @@ -192,9 +209,76 @@ /*********************************************************************//** * @brief + * The handleStandbyModeCheckUpdatedImageStates function handles the standby + * check the updated image state. + * This state checks the validity of the updated image that the update + * was in progress. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state of the standby mode state machine + *************************************************************************/ +static MODE_STANDBY_STATE_T handleStandbyModeCheckUpdatedImageStates( void ) +{ + SW_UPDATE_RESP_STATUS_T resp; + U32 calcCRC = 0; + MODE_STANDBY_STATE_T state = STANDBY_RESET_BOOTLOADER_STATE; + SW_UPDATE_DESINTATION_T dest = getSWUpdateDestination(); + ACK_NACK_STATUS_T ackStatus = ACK; + BOOL status = FALSE; + + switch( dest ) + { + case UPDATE_FPGA: + status = isFPGAFlashSuccessful(); + ackStatus = ( TRUE == status ? ACK : NACK ); + break; + + case UPDATE_FIRMWARE: + status = runFWIntegrityTest(); + ackStatus = ( TRUE == status ? ACK : NACK ); + break; + + default: + // Do nothing + break; + } + + // NOTE: FPGA is check in self configure + resp.msgID = getCurrentCmdMessageID(); + resp.msgAckNackStatus = ackStatus; + resp.spareSpace = 0; + resp.msgCRC = crc32( calcCRC, (U08*)&resp, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) ); + + // If both firmware and FPGA results passed, send an ack otherwise send a nack + sendAckNackStatusFromBootloader( (U08*)&resp ); + + return state; +} + +/*********************************************************************//** + * @brief + * The handleStandyModeResetBootloaderState function handles the standby + * reset bootloader state. + * This state resets the bootloader and transitions to idle state. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state of the standby mode state machine + *************************************************************************/ +static MODE_STANDBY_STATE_T handleStandyModeResetBootloaderState( void ) +{ + MODE_STANDBY_STATE_T state = STANDBY_IDLE_STATE; + + // Reset the bootloader regardless of whether the update was successful or not + resetBootloader(); + + return state; +} + +/*********************************************************************//** + * @brief * The jumpToApplication function handles the jump to application commands. * This function, disables interrupts that were used in the bootloader and - * then it jumps to the fimrware start address. + * then it jumps to the firmware start address. * @details \b Inputs: none * @details \b Outputs: none * @return none @@ -217,5 +301,18 @@ while(1); } +/*********************************************************************//** + * @brief + * The resetBootloader function resets the bootloader by soft reseting the + * processor. + * @details \b Inputs: none + * @details \b Outputs: none + * @return none + *************************************************************************/ +static void resetBootloader( void ) +{ + systemREG1->SYSECR = (0x2) << 14; // Reset processor +} + /**@}*/ Index: firmware/App/Modes/ModeUpdate.c =================================================================== diff -u -rab214e8ea52d8433b7cee58f5aaff49fc759310d -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Modes/ModeUpdate.c (.../ModeUpdate.c) (revision ab214e8ea52d8433b7cee58f5aaff49fc759310d) +++ firmware/App/Modes/ModeUpdate.c (.../ModeUpdate.c) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -132,11 +132,11 @@ switch( dest ) { - // TODO check the image in firmware and then both cases reset the bootloader. - // Come back and wait for the update broadcast for 3 seconds and if not, jump case UPDATE_FPGA: - if ( TRUE == isFPGAFlashComplete() ) + if ( FALSE == isFPGASelfConfigureInProgress() ) { + // Before tranistioning back to standby for the final verification, the self configure part + // of FPGA should be completed. requestNewOperationMode( MODE_STAND ); } break; Index: firmware/App/Services/Download.c =================================================================== diff -u -r2823873d5790228595fb991e52e78e2fd0d5987c -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/Download.c (.../Download.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) +++ firmware/App/Services/Download.c (.../Download.c) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -23,15 +23,6 @@ // ********** private data ********** -/// Software update response status structure -typedef struct -{ - U16 msgID; ///< Message ID. - U08 msgAckNackStatus; ///< Message ack or nack status. - U08 spareSpace; ///< Message spare byte. - U32 msgCRC; ///< Message CRC. -} SW_UPDATE_RESP_STATUS_T; - /// Software update command status structure typedef struct { @@ -199,6 +190,19 @@ return SWUpdateRCVStatus.msgID; } +/*********************************************************************//** + * @brief + * The getCurrentCmdMessageID function returns the current command message + * ID that has been received with command payload. + * @details \b Inputs: SWUpdateCmdStatus + * @details \b Outputs: none + * @return the current command message ID with update payload + *************************************************************************/ +U16 getCurrentCmdMessageID() +{ + return SWUpdateCmdStatus.msgID; +} + // ********** private functions ********** /*********************************************************************//** @@ -233,31 +237,28 @@ SWUpdateSpecs.dest = (SW_UPDATE_DESINTATION_T)SWUpdateCmdStatus.destination; ackStatus = ACK; - if ( UPDATE_FPGA == SWUpdateSpecs.dest ) + switch ( SWUpdateSpecs.cmd ) { - switch ( SWUpdateSpecs.cmd ) - { - case UPDATE_CMD_START: - // If the update destination is FPGA, signal FPGA to prepare for the update. - signalFPGAToPrepareForUpdate(); - break; + case UPDATE_CMD_START: + // If the update destination is FPGA, signal FPGA to prepare for the update. + signalFPGAToPrepareForUpdate(); + break; - case UPDATE_CMD_CONFIG_FPGA: - // Signal FPGA to self configure after the update is finished. - signalFPGAToSelfConfigure(); - break; + case UPDATE_CMD_CONFIG_FPGA: + // Signal FPGA to self configure after the update is finished. + signalFPGAToSelfConfigure(); + break; - default: - // Do nothing for the rest of the commands - break; - } + default: + // Do nothing for the rest of the commands + break; } } - if ( SWUpdateSpecs.dest != UPDATE_FPGA ) + if ( ( UPDATE_CMD_START == SWUpdateSpecs.cmd ) && ( SWUpdateSpecs.dest != UPDATE_FPGA ) ) { - // Send the result of the command received for firmware. - // FPGA is delayed and it takes a while to prepare it so ack is not sent immediately + // If the command is start send the ack immediately. The rest of the commands are delayed (e.g. verify - because action is needed) + // The start command in FPGA also needs the FPGA to be prepare itself so it will have a delayed start prepareAndSendBootLoaderResponseMessage( msgID, ackStatus ); } @@ -390,7 +391,7 @@ resp.spareSpace = 0; resp.msgCRC = crc32( calcCRC, (U08*)&resp, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) ); - sendAckNackStatusFromFirmware( (U08*)&resp ); // TODO do we have to retry if send failed? + sendAckNackStatusFromBootloader( (U08*)&resp ); // TODO do we have to retry if send failed? } /*********************************************************************//** @@ -446,13 +447,6 @@ status = signalFPGAToWriteToFlash( SWUpdateRCVStatus.SWUpdateBuffer, fpgaPayloadLengthBytes ); - // TODO remove this code - //if ( fpgaPayloadLengthBytes < SW_UPDATE_FLASH_BUFFER_SIZE ) - //{ - // // TODO this should be a command and not the last buffer because what if the last payload is 256 bytes? - // signalFPGAToSelfConfigure(); - //} - if ( TRUE == status ) { // The update payload has been enqueued successfully, clear the raw buffer but keep the receive buffer since the enqueue Index: firmware/App/Services/Download.h =================================================================== diff -u -rf6fd9dfd1a30412e237ff45ebee44854f0e2d4b2 -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/Download.h (.../Download.h) (revision f6fd9dfd1a30412e237ff45ebee44854f0e2d4b2) +++ firmware/App/Services/Download.h (.../Download.h) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -33,6 +33,8 @@ U16 getCurrentUpdateMessageID(); +U16 getCurrentCmdMessageID(); + /**@}*/ #endif Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r2823873d5790228595fb991e52e78e2fd0d5987c -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 2823873d5790228595fb991e52e78e2fd0d5987c) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -197,10 +197,6 @@ static U08 fpgaDataToWriteBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; ///< FPGA data to write to FPGA flash buffer. static U32 fpgaDataLenToWrite; ///< FPGA data length to write to FPGA. -static U08 tempPrevJob; -static U16 tempPrevFlash; -static U16 tempPrevFIFO; - static const U08 FPGA_RESET_FLASH_CMD = 0x01; ///< FPGA reset flash command. static const U08 FPGA_ERASE_FIFO_CMD = 0x08; ///< FPGA erase FIFO command. static const U08 FPGA_ENABLE_FLASH_CMD = 0x00; ///< FPGA enable flash command. @@ -327,7 +323,7 @@ break; } - publishDataTemp(); + //publishDataTemp(); } /*********************************************************************//** @@ -360,23 +356,38 @@ *************************************************************************/ BOOL isFPGAIDValid( void ) { - // TODO do we still need to check the FPGA ID? + BOOL status = FALSE; //TRUE; + + // TODO the FPGA ID is not checked for now so it is assumed that FPGA is valid //BOOL status = ( STACK_FPGA_ID[ BL_STACK_ID ] == fpgaHeader.fpgaId ? TRUE : FALSE ); - BOOL status = FALSE; + return status; +} +/*********************************************************************//** + * @brief + * The isFPGASelfConfigureInProgress function returns the status of FPGA self + * configure. TRUE if the self configure is in progress otherwise, FALSE. + * @details \b Inputs: fpgaFlashStatus + * @details \b Outputs: none + * @return TRUE if flash is in progress otherwise, FALSE + *************************************************************************/ +BOOL isFPGASelfConfigureInProgress( void ) +{ + BOOL status = ( FPGA_UPDATE_STAGE_SELF_CONFIGURE == fpgaFlashStatus.fpgaUpdateStage ? TRUE : FALSE ); + return status; } /*********************************************************************//** * @brief - * The isFPGAFlashComplete function returns the status of FPGA flash. So + * The isFPGAFlashSuccessful function returns the status of FPGA flash. So * TRUE if the flash is complete, otherwise, FALSE. * @details \b Inputs: fpgaFlashStatus * @details \b Outputs: none - * @return TRUE if flash is complete otherwise, FALSE + * @return TRUE if flash is successful otherwise, FALSE *************************************************************************/ -BOOL isFPGAFlashComplete( void ) +BOOL isFPGAFlashSuccessful( void ) { BOOL status = ( FPGA_UPDATE_STAGE_UPDATE_COMPLETE == fpgaFlashStatus.fpgaUpdateStage ? TRUE : FALSE ); @@ -430,7 +441,6 @@ status = TRUE; memset( &fpgaDataToWriteBuffer, 0x0, SW_UPDATE_FLASH_BUFFER_SIZE ); memcpy( &fpgaDataToWriteBuffer, data, len ); - enqueue( FPGA_FLASH_WRITE_DATA ); } @@ -897,25 +907,16 @@ static void publishDataTemp( void ) { - // TODO test code remove - //if ( ( tempPrevJob != fpgaJobsQStatus.fpgaCurrentJob ) || ( tempPrevFlash != fpgaReadRegsStatus.flashStatus ) || ( tempPrevFIFO != fpgaFlashStatus.fpgaRemainingFIFOCountBytes ) ) - { - U08 data[8]; - data[0] = GET_MSB_OF_WORD( getCurrentUpdateMessageID() ); - data[1] = GET_LSB_OF_WORD( getCurrentUpdateMessageID() ); - data[2] = GET_MSB_OF_WORD( fpgaReadRegsStatus.fifoCount ); - data[3] = GET_LSB_OF_WORD( fpgaReadRegsStatus.fifoCount ); - data[4] = GET_MSB_OF_WORD( fpgaReadRegsStatus.flashStatus ); - data[5] = GET_LSB_OF_WORD( fpgaReadRegsStatus.flashStatus ); - data[6] = fpgaJobsQStatus.fpgaCurrentJob; - data[7] = (U08)fpgaState; - broadcastDataTestRemove(data); - - tempPrevJob = fpgaJobsQStatus.fpgaCurrentJob; - tempPrevFlash = fpgaReadRegsStatus.flashStatus; - tempPrevFIFO = fpgaFlashStatus.fpgaRemainingFIFOCountBytes; - } - // TODO test code remove + U08 data[8]; + data[0] = GET_MSB_OF_WORD( getCurrentUpdateMessageID() ); + data[1] = GET_LSB_OF_WORD( getCurrentUpdateMessageID() ); + data[2] = GET_MSB_OF_WORD( fpgaReadRegsStatus.fifoCount ); + data[3] = GET_LSB_OF_WORD( fpgaReadRegsStatus.fifoCount ); + data[4] = GET_MSB_OF_WORD( fpgaReadRegsStatus.flashStatus ); + data[5] = GET_LSB_OF_WORD( fpgaReadRegsStatus.flashStatus ); + data[6] = fpgaJobsQStatus.fpgaCurrentJob; + data[7] = (U08)fpgaState; + broadcastDataTestRemove(data); } /*********************************************************************//** @@ -1010,24 +1011,6 @@ break; } - - //if ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob ) - //{ - // // Set the write length from the buffer length provided - // jobSize = (U16)fpgaDataLenToWrite; - //} - // - //if ( FPGA_SELF_CONFIGURE == fpgaJobsQStatus.fpgaCurrentJob ) - //{ - // // TODO remove? - // memset( &fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN ); - // memcpy( &fpgaReadRegsStatus, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], JOBS_SPECS[ FPGA_READ_MULTI_BOOT_STATUS ].fpgaJobSize ); - // processFPGAFlashRegistersRead(); - // - // // Once self configure is sent the FPGA will be unresponsive so there will be no ack back - // state = FPGA_IDLE_STATE; - //} - firstCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize; secondCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize + 1; Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r621896c8a4cc9204a12a7243ccef729c37e50c52 -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 621896c8a4cc9204a12a7243ccef729c37e50c52) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -29,7 +29,8 @@ void signalFPGAReceiptCompleted( void ); BOOL isFPGAIDValid( void ); -BOOL isFPGAFlashComplete( void ); +BOOL isFPGASelfConfigureInProgress( void ); +BOOL isFPGAFlashSuccessful( void ); void signalFPGAToPrepareForUpdate( void ); BOOL signalFPGAToWriteToFlash( U08* data, U32 len ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r5645305f9349c5c64be5560982bdf1abd5edb0fb -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5645305f9349c5c64be5560982bdf1abd5edb0fb) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -76,14 +76,14 @@ /*********************************************************************//** * @brief - * The sendAckNackStatusFromFirmware function sends the ack or nack status + * The sendAckNackStatusFromBootloader function sends the ack or nack status * of a received message. * @details \b Inputs: none * @details \b Outputs: none * @param data pointer to the data to be sent * @return TRUE if the CAN transmit was successful otherwise, FALSE *************************************************************************/ -BOOL sendAckNackStatusFromFirmware( U08* data ) +BOOL sendAckNackStatusFromBootloader( U08* data ) { BOOL status = FALSE; U32 respMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ][ FW_STACKS_RESP_MAIL_BOX_INDEX ]; Index: firmware/App/Services/SystemComm.h =================================================================== diff -u -r0c085209bea23f66011059a7c19796c1e4b246fa -rb887b4a2796de3b26be07619809f8f4146955867 --- firmware/App/Services/SystemComm.h (.../SystemComm.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa) +++ firmware/App/Services/SystemComm.h (.../SystemComm.h) (revision b887b4a2796de3b26be07619809f8f4146955867) @@ -20,7 +20,7 @@ void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOX_T mailBox ); -BOOL sendAckNackStatusFromFirmware( U08* data ); +BOOL sendAckNackStatusFromBootloader( U08* data ); BOOL broadcastDataTestRemove( U08* data );