Index: firmware/App/Services/CommBuffers.c =================================================================== diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -rc74c1d99a011dd0fb7f98f183faecda675221fce --- firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795) +++ firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision c74c1d99a011dd0fb7f98f183faecda675221fce) @@ -1,257 +1,163 @@ -/* - * CommBuffers.c - * - * Created on: Aug 2, 2024 - * Author: fw - */ -#include "string.h" // For memcpy -#include "can.h" +#include // For memcpy #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 +/** + * @addtogroup CommBuffers + * @{ + */ -typedef struct -{ - U08 msgID; - U08 updateCmd; - U16 cyberRandom; - U32 msgCRC; -} SW_UPDATE_CMD_STATUS_T; +// ********** private definitions ********** -typedef struct -{ - U32 SWUpdateFrameCount; - U08 msgID; - U08 updateDest; - U16 cyberIndex; - U32 msgCRC; - U08 SWUpdateBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; -} SW_UPDATE_RCV_STATUS_T; +#define MAX_NUM_OF_CAN_BYTES ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE ) ///< Maximum number of CAN bytes. +// ********** private data ********** + +/// Software update buffer structure typedef struct { - U08 msgID; - U08 msgAckNackStatus; - U16 cyberRandom; - U32 msgCRC; -} SW_UPDATE_RESP_STATUS_T; + U32 SWUpdateFrameCount; ///< Software update frame count. + U08 SWUpdateBuffer[ MAX_NUM_OF_CAN_BYTES ]; ///< Software update buffer. +} SW_UPDATE_BUFFER_T; -static const U32 NUM_OF_CAN_FRAMES_TO_UPDATE = ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE ) / CAN_MESSAGE_PAYLOAD_SIZE; +static SW_UPDATE_BUFFER_T SWUpdateBuffer[ NUM_OF_SW_UPDATE_MBOXES ]; ///< Software update buffer array. -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 -}; +// ********** private function prototypes ******** -static SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus; -static SW_UPDATE_RCV_STATUS_T SWUpdateRcvStatus; -static SW_UPDATE_BUFFER_STATUS_T SWUpdateBufferStatus; - -static U32 FORTESTREMOVE = 0; - -static void consumeReceivedUpdateCANFrame( U08* data ); -static void processReceivedUpdateCANFrame( void ); -static void processRecievedCmdCANFrame( U08* data ); - +/*********************************************************************//** + * @brief + * The initCommBuffers function initializes the CommBuffers unit. + * @details Inputs: none + * @details Outputs: CommBuffers unit initialized. + * @return none + *************************************************************************/ void initCommBuffers( void ) { - clearSWUpdateBuffer( TRUE ); - clearSWUpdateBuffer( FALSE ); + SW_UPDATE_CAN_MAIL_BOX_T mailBox; + + for ( mailBox = SW_UPDATE_NOT_USED; mailBox < NUM_OF_SW_UPDATE_MBOXES; mailBox++ ) + { + clearCommBuffer( mailBox ); + } } -void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOXES_T MailBox ) +/*********************************************************************//** + * @brief + * The addToCommBuffer function adds data of specified length to a given + * communication buffer. + * @note This function will add to the active side of the double buffer. + * @note This function is thread safe. IRQ interrupts are disabled during + * buffer operations. + * @details Inputs: SWUpdateBuffer[] + * @details Outputs: SWUpdateBuffer[] + * @param mailbox ID of buffer to add data to + * @param data Pointer to byte array containing data to add to buffer + * @param len Length of data (in bytes) + * @return TRUE if data added to buffer successfully, FALSE if not + *************************************************************************/ +BOOL addToCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len ) { - // TODO do we need check the range of the messages? + BOOL status = FALSE; - U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - - if ( SW_UPDATE_COMMAD == MailBox ) + if ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) { - if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) ) - { - U32 result = canGetData( canREG1, MailBox, data ); + _disable_IRQ(); + U32 currentFrameCount = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount; - if ( result != 0 ) - { - processRecievedCmdCANFrame( data ); - } - } - } - else - { - SW_UPDATE_CAN_MAIL_BOXES_T thisStackMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ]; - - if ( thisStackMailBox == MailBox ) + // Check if the number of bytes is less than the allowed bytes in the mailbox buffer. + if ( ( currentFrameCount * CAN_MESSAGE_PAYLOAD_SIZE ) <= MAX_NUM_OF_CAN_BYTES ) { - if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) ) - { - U32 result = canGetData( canREG1, MailBox, data ); + U32 currentBufferIndex = currentFrameCount * len; - if ( result != 0 ) - { - consumeReceivedUpdateCANFrame( data ); - } - } + // Copy the received can frame into the buffer + memcpy( SWUpdateBuffer[ mailBox ].SWUpdateBuffer + currentBufferIndex, data, len ); + + // Increment the current frame count + SWUpdateBuffer[ mailBox ].SWUpdateFrameCount += 1; + status = TRUE; } + _enable_IRQ(); } -} -void getSWUpdateBufferStatus( SW_UPDATE_BUFFER_STATUS_T* status ) -{ - memcpy( status, &SWUpdateBufferStatus, sizeof( SW_UPDATE_BUFFER_STATUS_T ) ); + return status; } - -void getSWUpdateBuffer( U08* data ) +/*********************************************************************//** + * @brief + * The getFromCommBuffer function fills a given byte array with a specified + * number of bytes from a given buffer and returns the number of bytes + * retrieved from the buffer. + * @note This function will draw from the inactive side of the double buffer + * and, if needed, switch double buffers to draw the rest of the requested data. + * @note This function is thread safe. IRQ interrupts are disabled during buffer + * operations. + * @details Inputs: SWUpdateBuffer[] + * @details Outputs: none + * @param mailbox ID of buffer to retrieve data from + * @param data Pointer to byte array to populate with buffer data + * @param len Number of bytes to retrieve from buffer into given byte array. + * @return the number of bytes retrieved. + *************************************************************************/ +BOOL getCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len ) { - memcpy( data, &SWUpdateRcvStatus.SWUpdateBuffer, sizeof( SWUpdateRcvStatus.SWUpdateBuffer ) ); -} + BOOL status = FALSE; -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 ) ) + if ( ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) && ( len <= MAX_NUM_OF_CAN_BYTES ) ) { - clearSWUpdateBuffer( cmd ); + _disable_IRQ(); + memcpy( data, SWUpdateBuffer[ mailBox ].SWUpdateBuffer, len ); + status = TRUE; + _enable_IRQ(); } -} -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 ) ); - } + return status; } - -// ********** private functions ********** - -static void consumeReceivedUpdateCANFrame( U08* data ) +/*********************************************************************//** + * @brief + * The getNumberOfBytesInBuffer function determines how many bytes + * are currently contained in a given comm buffer. Both sides of the + * double buffers are considered for this. + * @details Inputs: SWUpdateBuffer[] + * @details Outputs: none + * @param mailbox ID of buffer to get byte count for + * @return the number of bytes currently in the given comm buffer. + *************************************************************************/ +S32 getNumberOfBytesInBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox ) { - 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; + S32 bytes = -1; - memcpy( SWUpdateRcvStatus.SWUpdateBuffer + currentBufferIndex, data, CAN_MESSAGE_PAYLOAD_SIZE ); - } - - SWUpdateRcvStatus.SWUpdateFrameCount++; - - //if ( NUM_OF_CAN_FRAMES_TO_UPDATE == SWUpdateRcvStatus.SWUpdateFrameCount ) - if ( SWUpdateRcvStatus.SWUpdateFrameCount % NUM_OF_CAN_FRAMES_TO_UPDATE == 0 ) - { - processReceivedUpdateCANFrame(); - - // TODO REmove - if ( FORTESTREMOVE == 1 ) - { - BOOL test = FALSE; - } - FORTESTREMOVE++; - //sendAckNackStatusFromFirmware( ACK, FALSE ); - //clearSWUpdateBuffer( FALSE ); - // TODO Remove - } - else - { - //SWUpdateRcvStatus.SWUpdateFrameCount++; - } + if ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) + { + bytes = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount * CAN_MESSAGE_PAYLOAD_SIZE; } + + return bytes; } -static void processReceivedUpdateCANFrame( void ) +/*********************************************************************//** + * @brief + * The clearBuffer function clears (empties) a given buffer. + * @note This function is thread safe. IRQ interrupts are disabled while + * buffers are being cleared. + * @details Inputs: none + * @details Outputs: given buffer is cleared. + * @param buffer ID of the buffer to clear + * @return none + *************************************************************************/ +void clearCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox ) { - 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 ) + _disable_IRQ(); + if ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) { - 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; - } + memset( &SWUpdateBuffer[ mailBox ], 0x0, sizeof( SW_UPDATE_BUFFER_T ) ); } + _enable_IRQ(); } -static void processRecievedCmdCANFrame( U08* data ) -{ - ACK_NACK_STATUS_T ackStatus; +// ********** private functions ********** - 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 ); -} -