Index: firmware/App/Services/CommBuffers.c =================================================================== diff -u -ra60ec05d359c0d3f014015e9080b6dbcef0fea28 -rd5c5b1d2bc42b166f1ccff1aa4b2441db8f06d4b --- firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision a60ec05d359c0d3f014015e9080b6dbcef0fea28) +++ firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision d5c5b1d2bc42b166f1ccff1aa4b2441db8f06d4b) @@ -1,59 +1,57 @@ -/************************************************************************** - * - * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. - * - * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN - * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. - * - * @file CommBuffers.c - * - * @date 08-Oct-2019 - * @author S. Nash - * - * @brief CommBuffers service module. Provides data buffering functionality. \n - * Data coming in via CAN/UART Rx interrupts can be placed in a buffer to \n - * be processed at a later time. Data is double buffered to prevent \n - * contention between Rx/Tx interrupts and the processing thread(s). \n - * Data to be transmitted via CAN/UART can be placed in a buffer to be sent \n - * when the transmitter becomes available. \n - * If a buffer becomes too full to service more data, a s/w fault is triggered. - * - **************************************************************************/ +/************************************************************************** +* +* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file CommBuffers.c +* +* @author (last) Dara Navaei +* @date (last) 02-Oct-2020 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ #include #include // for memcpy() -#include "CommBuffers.h" +#include "CommBuffers.h" +#include "SystemComm.h" #include "SystemCommMessages.h" #include "Timers.h" +/** + * @addtogroup CommBuffers + * @{ + */ + // ********** private definitions ********** -#define COMM_BUFFER_LENGTH 512 // max bytes in each comm buffer (double if you count double buffers) -#define DOUBLE_BUFFERS 2 // need 2 buffers for double buffering -#define BUFFER_OVERFLOW_PERSISTENCE_MS 5000 // how many ms buffer overflows must persist before fault +#define COMM_BUFFER_LENGTH 512 ///< max bytes in each comm buffer (each side of double buffer is this size) +#define DOUBLE_BUFFERS 2 ///< need 2 buffers for double buffering +#define BUFFER_OVERFLOW_PERSISTENCE_MS 5000 ///< how many ms buffer overflows must persist before fault // ********** private data ********** -static volatile U32 commBufferByteCount[ NUM_OF_COMM_BUFFERS ][ DOUBLE_BUFFERS ]; // for each buffer, how many bytes does it contain? (also index to next available) -static volatile U32 activeDoubleBuffer[ NUM_OF_COMM_BUFFERS ]; // for each buffer, which double buffer is being fed right now? -static U08 commBuffers[ NUM_OF_COMM_BUFFERS ][ DOUBLE_BUFFERS ][ COMM_BUFFER_LENGTH ]; // each is double buffered to avoid thread contention -static volatile BOOL bufferGetLock[ NUM_OF_COMM_BUFFERS ]; // prevent getter from accessing active buffer while add in progress -static U32 firstBufferOverflowTimeStamp = 0; // time stamp of a prior overflow event - allows for an overflow persistence check +static volatile U32 commBufferByteCount[ NUM_OF_COMM_BUFFERS ][ DOUBLE_BUFFERS ]; ///< for each buffer, how many bytes does it contain? (also index to next available) +static volatile U32 activeDoubleBuffer[ NUM_OF_COMM_BUFFERS ]; ///< for each buffer, which double buffer is being fed right now? +static U08 commBuffers[ NUM_OF_COMM_BUFFERS ][ DOUBLE_BUFFERS ][ COMM_BUFFER_LENGTH ]; ///< each is double buffered to avoid thread contention +static U32 firstBufferOverflowTimeStamp = 0; ///< time stamp of a prior overflow event - allows for an overflow persistence check // ********** private function prototypes ********** -static void clearBuffer( COMM_BUFFER_T buffer ); static U32 switchDoubleBuffer( COMM_BUFFER_T buffer ); static void getDataFromInactiveBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ); -/************************************************************************* +/*********************************************************************//** * @brief * The initCommBuffers function initializes the CommBuffers module. * @details * Inputs : none * Outputs : CommBuffers module initialized. - * @param none * @return none *************************************************************************/ void initCommBuffers( void ) @@ -67,48 +65,51 @@ } } -/************************************************************************* +/*********************************************************************//** * @brief - * The clearBuffer function clears (empties) a given buffer. \n - * Caller should ensure buffer won't be used while this function is clearing \n + * The clearBuffer function clears (empties) a given buffer. + * Caller should ensure buffer won't be used while this function is clearing * the buffer. * @details * Inputs : none * Outputs : given buffer is cleared. - * @param buffer : the buffer to clear + * @param buffer the buffer to clear * @return none *************************************************************************/ -static void clearBuffer( COMM_BUFFER_T buffer ) +void clearBuffer( COMM_BUFFER_T buffer ) { if ( buffer < NUM_OF_COMM_BUFFERS ) { - S32 d,i; + S32 d; - activeDoubleBuffer[ buffer ] = 0; - for ( d = 0; d < DOUBLE_BUFFERS; d++ ) - { - commBufferByteCount[ buffer ][ d ] = 0; - for ( i = 0; i < COMM_BUFFER_LENGTH; i++ ) - { - commBuffers[ buffer ][ d ][ i ] = 0; - } - } - } + // thread protection for queue operations + _disable_IRQ(); + + activeDoubleBuffer[ buffer ] = 0; + for ( d = 0; d < DOUBLE_BUFFERS; d++ ) + { + commBufferByteCount[ buffer ][ d ] = 0; + memset( &commBuffers[ buffer ][ d ][ 0 ], 0, COMM_BUFFER_LENGTH ); + } + + // release thread protection + _enable_IRQ(); + } } -/************************************************************************* +/*********************************************************************//** * @brief - * The addToCommBuffer function adds data of specified length to a specified \n - * communication buffer. S/W fault if buffer too full to add data. \n - * This function will always add to the active double buffer. \n - * This function should only be called from the background, general, or \n + * The addToCommBuffer function adds data of specified length to a specified + * communication buffer. S/W fault if buffer too full to add data. + * This function will always add to the active double buffer. + * This function should only be called from the background, general, or * priority tasks (BG or IRQ) for thread safety. * @details * Inputs : commBufferByteCount[], activeDoubleBuffer[] * Outputs : commBuffers[], commBufferByteCount[] - * @param buffer : which comm buffer to add data to - * @param data : pointer to byte array containing data to add - * @param len : length of data (in bytes) + * @param buffer which comm buffer to add data to + * @param data pointer to byte array containing data to add + * @param len length of data (in bytes) * @return TRUE if data added to buffer successfully, FALSE if not *************************************************************************/ BOOL addToCommBuffer( COMM_BUFFER_T buffer, U08* data, U32 len ) @@ -120,64 +121,61 @@ { BOOL bufferFull = FALSE; U32 activeBuffer; - U32 currentActiveBufCount; // where to start adding new data to buffer (after existing data) + U32 currentActiveBufCount; // where to start adding new data to buffer (after existing data) + + if ( ( FALSE == isHDOnlyCANNode() ) || ( FALSE == isCANBoxForXmit( (CAN_MESSAGE_BOX_T)buffer ) ) ) + { + // thread protection for queue operations + _disable_IRQ(); - // thread protection for queue operations - _disable_IRQ(); - bufferGetLock[ buffer ] = TRUE; + activeBuffer = activeDoubleBuffer[ buffer ]; + currentActiveBufCount = commBufferByteCount[ buffer ][ activeBuffer ]; - activeBuffer = activeDoubleBuffer[ buffer ]; - currentActiveBufCount = commBufferByteCount[ buffer ][ activeBuffer ]; + // check to make sure buffer is not too full to service this add + if ( len <= ( COMM_BUFFER_LENGTH - currentActiveBufCount ) ) + { + U08 *buffPtr; // buffer destination for added data - // check to make sure buffer is not too full to service this add - if ( len <= ( COMM_BUFFER_LENGTH - currentActiveBufCount ) ) - { - U08 *buffPtr; // buffer destination for added data - - // set destination pointer to end of active buffer data - buffPtr = &commBuffers[ buffer ][ activeBuffer ][ currentActiveBufCount ]; - // copy source data to destination buffer - memcpy( buffPtr, data, len ); - // adjust buffer count per this data add (also reserves space to add data before releasing thread protection) - commBufferByteCount[ buffer ][ activeBuffer ] += len; + // set destination pointer to end of active buffer data + buffPtr = &commBuffers[ buffer ][ activeBuffer ][ currentActiveBufCount ]; + // copy source data to destination buffer + memcpy( buffPtr, data, len ); + // adjust buffer count per this data add (also reserves space to add data before releasing thread protection) + commBufferByteCount[ buffer ][ activeBuffer ] += len; + // data successfully added to buffer + result = TRUE; + } + else // buffer too full to add this much data + { + bufferFull = TRUE; + } // release thread protection - bufferGetLock[ buffer ] = FALSE; - _enable_IRQ(); - // data successfully added to buffer - result = TRUE; - } - else // buffer too full to add this much data - { - bufferFull = TRUE; - clearBuffer( buffer ); - } - // release thread protection - bufferGetLock[ buffer ] = FALSE; - _enable_IRQ(); + _enable_IRQ(); + } + // if buffer was full, check persistence - trigger s/w fault if persists if ( TRUE == bufferFull ) { +#ifdef DEBUG_ENABLED + char debugStr[ 100 ]; + sprintf( debugStr, "Buf OF:#%3d,%3d, %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", buffer, len, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] ); + sendDebugData( (U08*)debugStr, strlen(debugStr) ); + sendDebugDataToUI( (U08*)debugStr ); +#endif + clearBuffer( buffer ); // not first overflow? if ( firstBufferOverflowTimeStamp != 0 ) { // if buffer overflows persists, fault if ( calcTimeSince( firstBufferOverflowTimeStamp ) > BUFFER_OVERFLOW_PERSISTENCE_MS ) { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, len ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, (U32)buffer ) } } else // first overflow - set time stamp for persistence check { firstBufferOverflowTimeStamp = getMSTimerCount(); } -#ifdef DEBUG_ENABLED - { - // TODO - temporary debug code - remove later - char debugStr[ 256 ]; - sprintf( debugStr, "Comm Buffer Overflow:%5d \n", (U32)buffer ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); - } -#endif } else { // if good for persistence time period, reset persistence check @@ -189,28 +187,28 @@ } else // invalid buffer given { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_INVALID_BUFFER, buffer ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_ADD_INVALID_BUFFER, buffer ) } return result; } -/************************************************************************* +/*********************************************************************//** * @brief - * The getFromCommBuffer function fills a given byte array with a given \n - * number of bytes from a given buffer and returns the number of bytes \n - * retrieved from the buffer. This function will draw from the inactive \n - * double buffer first and, if needed, switch double buffers to draw the \n + * The getFromCommBuffer function fills a given byte array with a given + * number of bytes from a given buffer and returns the number of bytes + * retrieved from the buffer. This function will draw from the inactive + * double buffer first and, if needed, switch double buffers to draw the * rest of the requested data. - * Only one function in one thread should be calling this function for a given \n + * Only one function in one thread should be calling this function for a given * buffer. * @details * Inputs : commBuffers[], commBufferByteCount[], activeDoubleBuffer[] - * Outputs : commBuffers[], commBufferByteCount[], activeDoubleBuffer[], \n + * Outputs : commBuffers[], commBufferByteCount[], activeDoubleBuffer[], * and the given data array is populated with data from the buffer. - * @param buffer : which comm buffer to retrieve data from - * @param data : pointer to byte array to stuff data into - * @param len : # of bytes to retrieve into given data array. + * @param buffer which comm buffer to retrieve data from + * @param data pointer to byte array to stuff data into + * @param len number of bytes to retrieve into given data array. * @return the number of bytes retrieved. *************************************************************************/ U32 getFromCommBuffer( COMM_BUFFER_T buffer, U08* data, U32 len ) @@ -250,26 +248,26 @@ } else // invalid buffer given { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_GET_INVALID_BUFFER, buffer ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_GET_INVALID_BUFFER, buffer ) } return result; } -/************************************************************************* +/*********************************************************************//** * @brief - * The peekFromCommBuffer function fills a given byte array with a given \n - * number of bytes from a given buffer. This function does NOT consume \n - * the bytes - it only peeks at them. A call to numberOfBytesInCommBuffer() \n - * should be made before calling this function to determine how many bytes \n - * are currently in the buffer. Do not call this function with a "len" \n + * The peekFromCommBuffer function fills a given byte array with a given + * number of bytes from a given buffer. This function does NOT consume + * the bytes - it only peeks at them. A call to numberOfBytesInCommBuffer() + * should be made before calling this function to determine how many bytes + * are currently in the buffer. Do not call this function with a "len" * longer than what is currently in the buffer. * @details * Inputs : commBuffers[], commBufferByteCount[], activeDoubleBuffer[] - * Outputs : given array populated with requested # of bytes from the buffer. - * @param buffer : which comm buffer to retrieve data from - * @param data : pointer to byte array to stuff data into - * @param len : # of bytes to retrieve into given data array. + * Outputs : given array populated with requested number of bytes from the buffer. + * @param buffer which comm buffer to retrieve data from + * @param data pointer to byte array to stuff data into + * @param len number of bytes to retrieve into given data array. * @return the number of bytes retrieved. *************************************************************************/ U32 peekFromCommBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ) @@ -308,21 +306,21 @@ } else // invalid buffer given { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_PEEK_INVALID_BUFFER, buffer ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_PEEK_INVALID_BUFFER, buffer ) } return numOfBytesPeeked; } -/************************************************************************* +/*********************************************************************//** * @brief - * The numberOfBytesInCommBuffer function determines how many bytes \n - * are currently contained in a given comm buffer. Both double buffers \n + * The numberOfBytesInCommBuffer function determines how many bytes + * are currently contained in a given comm buffer. Both double buffers * are considered for this. * @details * Inputs : activeDoubleBuffer[], commBufferByteCount[] * Outputs : none - * @param buffer : which comm buffer to get byte count for + * @param buffer which comm buffer to get byte count for * @return the number of bytes in the given comm buffer. *************************************************************************/ U32 numberOfBytesInCommBuffer( COMM_BUFFER_T buffer ) @@ -335,33 +333,26 @@ U32 activeBuffer = activeDoubleBuffer[ buffer ]; U32 inactiveBuffer = GET_TOGGLE( activeBuffer, 0, 1 ); - if ( FALSE == bufferGetLock[ buffer ] ) - { - result = commBufferByteCount[ buffer ][ inactiveBuffer ] + commBufferByteCount[ buffer ][ activeBuffer ]; - } - else - { - result = commBufferByteCount[ buffer ][ inactiveBuffer ]; - } + result = commBufferByteCount[ buffer ][ inactiveBuffer ] + commBufferByteCount[ buffer ][ activeBuffer ]; } else // invalid buffer { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_COUNT_INVALID_BUFFER, buffer ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_COMM_BUFFERS_COUNT_INVALID_BUFFER, buffer ) } return result; } -/************************************************************************* +/*********************************************************************//** * @brief - * The switchDoubleBuffer function switches the active and inactive buffers \n - * for the given buffer. \n - * This function should only be called when the current inactive buffer has \n + * The switchDoubleBuffer function switches the active and inactive buffers + * for the given buffer. + * This function should only be called when the current inactive buffer has * been emptied. Any unconsumed data in inactive buffer will be lost. * @details * Inputs : activeDoubleBuffer[] * Outputs : activeDoubleBuffer[], commBufferByteCount[] - * @param buffer : which comm buffer to switch double buffers on + * @param buffer which comm buffer to switch double buffers on * @return the new active buffer for the given buffer. *************************************************************************/ static U32 switchDoubleBuffer( COMM_BUFFER_T buffer ) @@ -378,17 +369,17 @@ return inactiveBuffer; } -/************************************************************************* +/*********************************************************************//** * @brief - * The getDataFromInactiveBuffer function retrieves a given number of bytes \n - * from the inactive buffer of a given buffer. This function should only be \n + * The getDataFromInactiveBuffer function retrieves a given number of bytes + * from the inactive buffer of a given buffer. This function should only be * called by getFromCommBuffer(). Params will be pre-validated there. * @details * Inputs : commBuffers[], activeDoubleBuffer[], commBufferByteCount[] * Outputs : commBuffers[], activeDoubleBuffer[], commBufferByteCount[] - * @param buffer : which comm buffer get data from - * @param data : pointer to byte array to populate with data - * @param len : # of bytes to get from comm buffer + * @param buffer which comm buffer get data from + * @param data pointer to byte array to populate with data + * @param len number of bytes to get from comm buffer * @return none *************************************************************************/ static void getDataFromInactiveBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ) @@ -415,3 +406,5 @@ switchDoubleBuffer( buffer ); // switch will zero count off inactive buffer } } + +/**@}*/