/* * Download.c * * Created on: Aug 21, 2024 * Author: fw */ #include // For memcpy and memset #include "CommBuffers.h" #include "Download.h" #include "NVDataMgmt.h" #include "SystemComm.h" #include "Utilities.h" #define SW_UPDATE_FINAL_MSG_INDEX 0xFFFF #define SHIFT_BITS_TO_GET_TARGET 4 static const U32 NUM_OF_CAN_BYTES_FOR_UPDATE = SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE; typedef struct { U08 msgID; U08 msgAckNackStatus; U16 cyberRandom; U32 msgCRC; } SW_UPDATE_RESP_STATUS_T; typedef struct { U08 msgID; U08 updateCmd; U16 cyberRandom; U32 msgCRC; } SW_UPDATE_CMD_STATUS_T; typedef struct { U08 msgID; U08 updateDest; U16 cyberIndex; U32 msgCRC; U08 SWUpdateBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; } SW_UPDATE_RCV_STATUS_T; static SW_UPDATE_RCV_STATUS_T SWUpdateRCVStatus; static SW_UPDATE_CMD_T SWUpdateCommandState; static SW_UPDATE_CAN_MAIL_BOX_T thisStackMailBox; static void processIncomingCmdMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox ); static void processIncomingUpdateMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox ); static void prepareResponseMessage( U08 respOfMsgID, ACK_NACK_STATUS_T ackNack, SW_UPDATE_RESP_STATUS_T* respBuffer ); static void clearSWUpdateBuffer( void ); void initDownload( void ) { thisStackMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ]; clearSWUpdateBuffer(); clearSWUpdateCommandState(); } void execDownload( void ) { processIncomingCmdMessage( SW_UPDATE_COMMAD ); processIncomingUpdateMessage( thisStackMailBox ); } SW_UPDATE_CMD_T getSWUpdateCommandState( void ) { return SWUpdateCommandState; } void clearSWUpdateCommandState( void ) { SWUpdateCommandState = UPDATE_CMD_IDLE; } // ********** private functions ********** static void processIncomingCmdMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox ) { SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus; S32 numOfBytes = getNumberOfBytesInBuffer( mailBox ); BOOL status = getCommBuffer( mailBox, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) ); if ( ( TRUE == status ) && ( numOfBytes >= CAN_MESSAGE_PAYLOAD_SIZE ) ) { SW_UPDATE_RESP_STATUS_T resp; BOOL hasCRCPassed = FALSE; ACK_NACK_STATUS_T ackStatus = NACK; U32 calcCRC = 0; U08 msgID = SWUpdateCmdStatus.msgID; SW_UPDATE_DESINTATION_T dest = (SW_UPDATE_DESINTATION_T)( SWUpdateCmdStatus.updateCmd >> SHIFT_BITS_TO_GET_TARGET ); calcCRC = crc32( calcCRC, (U08*)&SWUpdateCmdStatus, MAX_CRC_CALC_DATA_SIZE ); hasCRCPassed = ( SWUpdateCmdStatus.msgCRC == calcCRC ? TRUE : FALSE ); // TODO remove hasCRCPassed = TRUE; // TODO remove if ( TRUE == hasCRCPassed ) { ackStatus = ACK; SWUpdateCommandState = (SW_UPDATE_CMD_T)( SWUpdateCmdStatus.updateCmd & MASK_OFF_NIBBLE_MSB ); if ( UPDATE_FPGA == dest ) { // signal FPGA to get ready in parallel } } prepareResponseMessage( msgID, ackStatus, &resp ); status = sendAckNackStatusFromFirmware( (U08*)&resp ); clearCommBuffer( mailBox ); } } static void processIncomingUpdateMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox ) { S32 bytesInBuffer = getNumberOfBytesInBuffer( mailBox ); if ( bytesInBuffer >= NUM_OF_CAN_BYTES_FOR_UPDATE ) { U32 calcCRC = 0; BOOL hasCRCPassed = FALSE; ACK_NACK_STATUS_T ackStatus = NACK; getCommBuffer( mailBox, (U08*)&SWUpdateRCVStatus, NUM_OF_CAN_BYTES_FOR_UPDATE ); calcCRC = crc32( calcCRC, SWUpdateRCVStatus.SWUpdateBuffer, MAX_CRC_CALC_DATA_SIZE ); hasCRCPassed = ( SWUpdateRCVStatus.msgCRC == calcCRC ? TRUE : FALSE ); // TODO remove hasCRCPassed = TRUE; // TODO remove if ( TRUE == hasCRCPassed ) { SW_UPDATE_RESP_STATUS_T resp; BOOL status = FALSE; switch ( SWUpdateRCVStatus.updateDest ) { case UPDATE_FIRMWARE: if ( SWUpdateRCVStatus.cyberIndex != SW_UPDATE_FINAL_MSG_INDEX ) { _disable_IRQ(); status = handleUpdatingFlash( SWUpdateRCVStatus.SWUpdateBuffer ); ackStatus = ( TRUE == status ? ACK : NACK ); _enable_IRQ(); } break; case UPDATE_FPGA: // TODO update FPGA // TODo FPGA last page done break; default: // Do nothing break; } prepareResponseMessage( SWUpdateRCVStatus.msgID, ackStatus, &resp ); status = sendAckNackStatusFromFirmware( (U08*)&resp ); // TODO do we have to retry if send failed? clearCommBuffer( mailBox ); } clearSWUpdateBuffer(); } } static void prepareResponseMessage( U08 respOfMsgID, ACK_NACK_STATUS_T ackNack, SW_UPDATE_RESP_STATUS_T* respBuffer ) { U32 calcCRC = 0; respBuffer->msgID = respOfMsgID; respBuffer->msgAckNackStatus = ackNack; respBuffer->cyberRandom = 0; respBuffer->msgCRC = crc32( calcCRC, (U08*)&respBuffer, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) ); } static void clearSWUpdateBuffer( void ) { memset( &SWUpdateRCVStatus, 0x0, sizeof( SW_UPDATE_RCV_STATUS_T ) ); }