#include // For memcpy #include "CommBuffers.h" #include "Utilities.h" /** * @addtogroup CommBuffers * @{ */ // ********** private definitions ********** #define UPDATE_PACKET_SIZE_BYTES ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_FRAME_SIZE ) ///< Software update packet size in bytes. /// Software update buffer structure typedef struct { U32 SWUpdateNumOfFramesCount; ///< Software update number of frame count. U32 SWUpdateFrameCount; ///< Software update frame count. U08 SWUpdateBuffer[ UPDATE_PACKET_SIZE_BYTES ]; ///< Software update buffer. } SW_UPDATE_BUFFER_T; // ********** private data ********** static SW_UPDATE_BUFFER_T SWUpdateBuffer[ NUM_OF_SW_UPDATE_MBOXES ]; ///< Software update buffer array. // ********** private function prototypes ******** /*********************************************************************//** * @brief * The initCommBuffers function initializes the CommBuffers unit. * @details Inputs: none * @details Outputs: CommBuffers unit initialized. * @return none *************************************************************************/ void initCommBuffers( void ) { SW_UPDATE_CAN_MAIL_BOX_T mailBox; for ( mailBox = SW_UPDATE_NOT_USED; mailBox < NUM_OF_SW_UPDATE_MBOXES; mailBox++ ) { clearCommBuffer( mailBox ); } } /*********************************************************************//** * @brief * The addToCommBuffer function adds data of specified length to a given * communication 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 ) { BOOL status = FALSE; if ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) { _disable_IRQ(); U32 currentFrameCount = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount; // Check if the number of bytes is less than the allowed bytes in the mailbox buffer. if ( ( currentFrameCount * CAN_MESSAGE_FRAME_SIZE ) <= UPDATE_PACKET_SIZE_BYTES ) { U32 currentBufferIndex = currentFrameCount * len; // Copy the received can frame into the buffer memcpy( SWUpdateBuffer[ mailBox ].SWUpdateBuffer + currentBufferIndex, data, len ); switch ( mailBox ) { case SW_UPDATE_COMMAD: // A command is only 1 frame of 8 bytes. SWUpdateBuffer[ mailBox ].SWUpdateNumOfFramesCount = NUM_OF_CMD_CAN_FRAMES; break; case SW_UPDATE_TD_UPDATE: case SW_UPDATE_DD_UPDATE: if ( 0 == SWUpdateBuffer[ mailBox ].SWUpdateFrameCount ) { // If the received command is a software update mailbox and if the frame count is 0, so it is the overhead frame. // In the overhead frame the 2nd and 3rd bytes are payload length and the two payloads are bitwised to get the payload length. U08 updatePayloadLenMSB = SWUpdateBuffer[ mailBox ].SWUpdateBuffer[ SW_UPDATE_LEN_MSB_INDEX ]; U08 updatePayloadLenLSB = SWUpdateBuffer[ mailBox ].SWUpdateBuffer[ SW_UPDATE_LEN_LSB_INDEX ]; U16 updatePayloadLength = updatePayloadLenMSB << SHIFT_8_BITS_FOR_BYTE_SHIFT | updatePayloadLenLSB; // Per the payload length, calculate the number of frames of 8 bytes that are needed to receive the entire update message. // Round up the number of frames with (payload length + 1 can frame (8 bytes) - 1) / 1 can frame (8 bytes) // After calculating the number of frames needed to receive the entire update payload add one more frame for the overhead frame. SWUpdateBuffer[ mailBox ].SWUpdateNumOfFramesCount = ( updatePayloadLength + CAN_MESSAGE_FRAME_SIZE - 1 ) / CAN_MESSAGE_FRAME_SIZE; SWUpdateBuffer[ mailBox ].SWUpdateNumOfFramesCount += 1; } break; default: // Do nothing. There are other mailboxes that do not need to be processed. break; } // Increment the current frame count SWUpdateBuffer[ mailBox ].SWUpdateFrameCount += 1; status = TRUE; } _enable_IRQ(); } return status; } /*********************************************************************//** * @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. * 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 ) { BOOL status = FALSE; if ( ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) && ( len <= UPDATE_PACKET_SIZE_BYTES ) ) { _disable_IRQ(); memcpy( data, SWUpdateBuffer[ mailBox ].SWUpdateBuffer, len ); status = TRUE; _enable_IRQ(); } return status; } /*********************************************************************//** * @brief * The isMessageComplete function checks whether a message (command or update) * has been fully received. * @details Inputs: SWUpdateBuffer[] * @details Outputs: none * @param mailbox ID of buffer to check the completeness of the message * @return TRUE if the messages has been fully received, otherwise FALSE *************************************************************************/ BOOL isMessageComplete( SW_UPDATE_CAN_MAIL_BOX_T mailBox ) { BOOL status = FALSE; U32 frameCnt = 0; U32 numOfFramesCnt = 0; switch ( mailBox ) { case SW_UPDATE_COMMAD: frameCnt = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount; numOfFramesCnt = SWUpdateBuffer[ mailBox ].SWUpdateNumOfFramesCount; break; case SW_UPDATE_TD_UPDATE: case SW_UPDATE_DD_UPDATE: frameCnt = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount; numOfFramesCnt = SWUpdateBuffer[ mailBox ].SWUpdateNumOfFramesCount; break; default: // Do nothing. There are other mailboxes that do not need to be processed. break; } // Check if the frame count is not 0 meaning that at least one frame is received prior to checking for the completion. if ( ( frameCnt > 0 ) && ( frameCnt == numOfFramesCnt ) ) { status = TRUE; } return status; } /*********************************************************************//** * @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 ) { _disable_IRQ(); if ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) { memset( &SWUpdateBuffer[ mailBox ], 0x0, sizeof( SW_UPDATE_BUFFER_T ) ); } _enable_IRQ(); } // ********** private functions ********** /**@}*/