/* * CommBuffers.c * * Created on: Aug 2, 2024 * Author: fw */ #include "string.h" // For memcpy #include "can.h" #include "CommBuffers.h" #include "Utilities.h" #define NUM_OF_FW_STACKS 3 #define CAN_MESSAGE_PAYLOAD_SIZE 8 #define SW_UPDATE_FINAL_MSG_INDEX 0xFFFF typedef struct { U08 msgID; U08 updateCmd; U16 cyberRandom; U32 msgCRC; } SW_UPDATE_CMD_STATUS_T; typedef struct { U32 SWUpdateFrameCount; U08 msgID; U08 updateDest; U16 cyberIndex; U32 msgCRC; U08 SWUpdateBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; } SW_UPDATE_RCV_STATUS_T; typedef struct { U08 msgID; U08 msgAckNackStatus; U16 cyberRandom; U32 msgCRC; } SW_UPDATE_RESP_STATUS_T; static const U32 NUM_OF_CAN_FRAMES_TO_UPDATE = ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE ) / CAN_MESSAGE_PAYLOAD_SIZE; static const SW_UPDATE_CAN_MAIL_BOXES_T RECEIVE_MSG_ID[ NUM_OF_FW_STACKS ] = { SW_UPDATE_TD_UPDATE, SW_UPDATE_DD_UPDATE, SW_UPDATE_RO_UPDATE }; static SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus; static SW_UPDATE_RCV_STATUS_T SWUpdateRcvStatus; static SW_UPDATE_BUFFER_STATUS_T SWUpdateBufferStatus; static void consumeReceivedUpdateCANFrame( U08* data ); static void processReceivedUpdateCANFrame( void ); static void processRecievedCmdCANFrame( U08* data ); void initCommBuffers( void ) { clearSWUpdateBuffer( TRUE ); clearSWUpdateBuffer( FALSE ); } void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOXES_T MailBox ) { // TODO do we need check the range of the messages? U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; if ( SW_UPDATE_COMMAD == MailBox ) { if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) ) { U32 result = canGetData( canREG1, MailBox, data ); if ( result != 0 ) { processRecievedCmdCANFrame( data ); } } } else { SW_UPDATE_CAN_MAIL_BOXES_T thisStackMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ]; if ( thisStackMailBox == MailBox ) { if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) ) { U32 result = canGetData( canREG1, MailBox, data ); if ( result != 0 ) { consumeReceivedUpdateCANFrame( data ); } } } } } void getSWUpdateBufferStatus( SW_UPDATE_BUFFER_STATUS_T* status ) { memcpy( status, &SWUpdateBufferStatus, sizeof( SW_UPDATE_BUFFER_STATUS_T ) ); } void getSWUpdateBuffer( U08* data ) { memcpy( data, &SWUpdateRcvStatus.SWUpdateBuffer, sizeof( SWUpdateRcvStatus.SWUpdateBuffer ) ); } void sendAckNackStatusFromFirmware( ACK_NACK_STATUS_T status, BOOL cmd ) { SW_UPDATE_RESP_STATUS_T resp; U32 calcCRC = 0; resp.msgID = ( TRUE == cmd ? SWUpdateCmdStatus.msgID : SWUpdateRcvStatus.msgID ); resp.msgAckNackStatus = status; resp.cyberRandom = 0; resp.msgCRC = crc32( calcCRC, (U08*)&resp, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) ); if ( 0 != canTransmit( canREG1, (U32)SW_UPDATE_RESP, (U08*)&resp ) ) { clearSWUpdateBuffer( cmd ); } } void clearSWUpdateBuffer( BOOL cmd ) { if ( FALSE == cmd ) { memset( &SWUpdateRcvStatus, 0x0, sizeof( SW_UPDATE_RCV_STATUS_T ) ); memset( &SWUpdateBufferStatus, 0x0, sizeof( SW_UPDATE_BUFFER_STATUS_T ) ); } else { memset( &SWUpdateCmdStatus, 0x0, sizeof( SW_UPDATE_CMD_STATUS_T ) ); } } // ********** private functions ********** static void consumeReceivedUpdateCANFrame( U08* data ) { if ( SWUpdateRcvStatus.SWUpdateFrameCount <= NUM_OF_CAN_FRAMES_TO_UPDATE ) { if ( 0 == SWUpdateRcvStatus.SWUpdateFrameCount ) { memcpy( &SWUpdateRcvStatus.msgID, data, sizeof( U08 ) ); data += sizeof( U08 ); memcpy( &SWUpdateRcvStatus.updateDest, data, sizeof( U08 ) ); data += sizeof( U08 ); memcpy( &SWUpdateRcvStatus.cyberIndex, data, sizeof( U16 ) ); data += sizeof( U16 ); memcpy( &SWUpdateRcvStatus.msgCRC, data, sizeof( U32 ) ); } else { U32 currentBufferIndex = ( SWUpdateRcvStatus.SWUpdateFrameCount - 1 ) * CAN_MESSAGE_PAYLOAD_SIZE; memcpy( SWUpdateRcvStatus.SWUpdateBuffer + currentBufferIndex, data, CAN_MESSAGE_PAYLOAD_SIZE ); } SWUpdateRcvStatus.SWUpdateFrameCount++; if ( SWUpdateRcvStatus.SWUpdateFrameCount % NUM_OF_CAN_FRAMES_TO_UPDATE == 0 ) { processReceivedUpdateCANFrame(); } } } static void processReceivedUpdateCANFrame( void ) { U32 calcCRC = 0; BOOL hasCRCPassed = FALSE; 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 ) { switch ( SWUpdateRcvStatus.updateDest ) { case UPDATE_FIRMWARE: if ( SWUpdateRcvStatus.cyberIndex != SW_UPDATE_FINAL_MSG_INDEX ) { SWUpdateBufferStatus.isSWUpdateBufferReady = TRUE; SWUpdateBufferStatus.dest = UPDATE_FIRMWARE; } else { sendAckNackStatusFromFirmware( ACK, FALSE ); clearSWUpdateBuffer( FALSE ); } break; case UPDATE_FPGA: SWUpdateBufferStatus.isSWUpdateBufferReady = TRUE; SWUpdateBufferStatus.dest = UPDATE_FPGA; break; default: // Do nothing break; } } } static void processRecievedCmdCANFrame( U08* data ) { ACK_NACK_STATUS_T ackStatus; U32 calcCRC = 0; BOOL hasCRCPassed = FALSE; memcpy( &SWUpdateCmdStatus.msgID, data, sizeof( U08 ) ); data += sizeof( U08 ); memcpy( &SWUpdateCmdStatus.updateCmd, data, sizeof( U08 ) ); data += sizeof( U08 ); memcpy( &SWUpdateCmdStatus.cyberRandom, data, sizeof( U16 ) ); data += sizeof( U16 ); memcpy( &SWUpdateCmdStatus.msgCRC, data, sizeof( U32 ) ); calcCRC = crc32( calcCRC, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) - sizeof( U32 ) ); hasCRCPassed = ( SWUpdateRcvStatus.msgCRC == calcCRC ? TRUE : FALSE ); ackStatus = ( TRUE == hasCRCPassed ? ACK : NACK ); sendAckNackStatusFromFirmware( ackStatus, TRUE ); }