/************************************************************************** * * Copyright (c) 2024-2024 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 SystemCommDD.c * * @author (last) Vinayakam Mani * @date (last) 05-Aug-2024 * * @author (original) Vinayakam Mani * @date (original) 05-Aug-2024 * ***************************************************************************/ #include // for memcpy() #include #include "can.h" #include "sci.h" #include "sys_dma.h" #include "Comm.h" //#include "DrainPump.h" //#include "Heaters.h" #include "Interrupts.h" #include "OperationModes.h" #include "Messaging.h" #include "Timers.h" #include "Utilities.h" /** * @addtogroup SystemCommDD * @{ */ // ********** private definitions ********** #define TD_COMM_TIMEOUT_IN_MS 2000 ///< TD has not sent any broadcast messages for this much time #define MAX_COMM_CRC_FAILURES 5 ///< maximum number of CRC errors within window period before alarm #define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window #define MAX_FPGA_CLOCK_SPEED_ERRORS 3 ///< maximum number of FPGA clock speed errors within window period before alarm #define MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< FPGA clock speed error window // ********** private data ********** /// Array of out-going CAN buffers. const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = { COMM_BUFFER_OUT_CAN_DD_ALARM, COMM_BUFFER_OUT_CAN_DD_2_TD, COMM_BUFFER_OUT_CAN_DD_2_RO, COMM_BUFFER_OUT_CAN_DD_BROADCAST, COMM_BUFFER_OUT_CAN_PC }; /// Array of in-coming CAN buffers. const COMM_BUFFER_T CAN_IN_BUFFERS[ NUM_OF_CAN_IN_BUFFERS ] = { COMM_BUFFER_IN_CAN_TD_ALARM, COMM_BUFFER_IN_CAN_UI_ALARM, COMM_BUFFER_IN_CAN_RO_ALARM, COMM_BUFFER_IN_CAN_TD_2_DD, COMM_BUFFER_IN_CAN_TD_BROADCAST, COMM_BUFFER_IN_CAN_RO_2_DD, COMM_BUFFER_IN_CAN_RO_BROADCAST, COMM_BUFFER_IN_CAN_UI_BROADCAST, COMM_BUFFER_IN_CAN_PC, }; static volatile BOOL ddIsOnlyCANNode = TRUE; ///< flag indicating whether DG is alone on CAN bus. static OVERRIDE_U32_T tdCommunicationStatus = {0, 0, 0, 0}; ///< has TD sent a message since last check static volatile U32 timeOfLastTDCheckIn = 0; ///< last time we received an TD broadcast // ********** private function prototypes ********** /*********************************************************************//** * @brief * The initSystemCommDD function initializes the DD SystemComm module. * @details \b Inputs: none * @details \b Outputs: SystemComm module initialized. * @return none *************************************************************************/ void initSystemCommDD( void ) { // Initialize common system comm unit initSystemComm(); // initialize bad message CRC time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC, MAX_COMM_CRC_FAILURES, MAX_COMM_CRC_FAILURE_WINDOW_MS ); // initialize FPGA clock speed error time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR, MAX_FPGA_CLOCK_SPEED_ERRORS, MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS); } /*********************************************************************//** * @brief * The isTDCommunicating function determines whether the TD is communicating * with the DD. * @details \b Inputs: tdIsCommunicating * @details \b Outputs: none * @return TRUE if TD has broadcast since last call, FALSE if not *************************************************************************/ BOOL isTDCommunicating( void ) { return getU32OverrideValue( &tdCommunicationStatus ); } /*********************************************************************//** * @brief * The isOnlyCANNode function determines whether the DD is the only node * currently on the CAN bus. * @details \b Inputs: ddIsOnlyCANNode * @details \b Outputs: none * @return TRUE if DD is only node on CAN bus, FALSE if not *************************************************************************/ BOOL isOnlyCANNode( void ) { return ddIsOnlyCANNode; } /*********************************************************************//** * @brief * The setOnlyCANNode function sets whether the DD is the only node * currently on the CAN bus. * @details \b Inputs: none * @details \b Outputs: ddIsOnlyCANNode * @return only TRUE if TD is only node on CAN bus, FALSE if not *************************************************************************/ void setOnlyCANNode( BOOL only ) { ddIsOnlyCANNode = only; } /*********************************************************************//** * @brief * The clearCANXmitBuffers function clears all CAN transmit buffers. * @details \b Inputs: CAN_OUT_BUFFERS[] * @details \b Outputs: CAN transmit buffers cleared. * @return none *************************************************************************/ void clearCANXmitBuffers( void ) { U32 i; for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) { clearBuffer( getOutBufferID( i ) ); } } /*********************************************************************//** * @brief * The checkForCommTimeouts function checks for sub-system communication timeout errors. * @details \b Inputs: timeOfLastDGCheckIn, timeOfLastUICheckIn * @details \b Outputs: possibly a comm t/o alarm * @return none *************************************************************************/ void checkForCommTimeouts( void ) { if ( TRUE == didTimeout( timeOfLastTDCheckIn, TD_COMM_TIMEOUT_IN_MS ) ) { tdCommunicationStatus.data = FALSE; setTDOperationMode( 0, 0 ); // If TD off or not connected, consider TD mode is fault. //stopHeater( DG_TRIMMER_HEATER ); // If TD off or not connected, ensure trimmer heater is off. } } /*********************************************************************//** * @brief * The getInBufferID function gets the buffer ID for a given buffer index. * @details \b Inputs: CAN_IN_BUFFERS[] * @details \b Outputs: none * @param idx incoming buffer index (e.g. 0 indicates first incoming buffer) * @return buffer id associated with given incoming buffer index *************************************************************************/ COMM_BUFFER_T getInBufferID( U32 idx ) { COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; // validate given index if ( idx < NUM_OF_CAN_IN_BUFFERS ) { result = CAN_IN_BUFFERS[ idx ]; } else { // TODO - s/w fault } return result; } /*********************************************************************//** * @brief * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs * within a set period of time. Assumed function is being called when a new * bad CRC is detected so a new bad CRC will be added to the list. * @details \b Inputs: badCRCTimeStamps[], badCRCListIdx, badCRCListCount * @details \b Outputs: possibly a "too many bad CRCs" alarm * @details \b Alarm: ALARM_ID_DD_COMM_TOO_MANY_BAD_CRCS when too many bad * message CRC seen. * @return none *************************************************************************/ void checkTooManyBadMsgCRCs( void ) { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_COMM_TOO_MANY_BAD_CRCS, 2 ); // 2 for DG } } /*********************************************************************//** * @brief * The getOutBufferID function gets the buffer ID for a given buffer index. * @details \b Inputs: CAN_OUT_BUFFERS[] * @details \b Outputs: none * @param idx outgoing buffer index (e.g. 0 indicates first outgoing buffer) * @return buffer id associated with given outgoing buffer index *************************************************************************/ COMM_BUFFER_T getOutBufferID( U32 idx ) { COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; // validate given index if ( idx < NUM_OF_CAN_OUT_BUFFERS ) { result = CAN_OUT_BUFFERS[ idx ]; } else { // TODO - s/w fault } return result; } /*********************************************************************//** * @brief * The processReceivedMessage function processes a given message. * @details \b Inputs: none * @details \b Outputs: message processed * @param message pointer to message to process * @return none *************************************************************************/ void processReceivedMessage( MESSAGE_T *message ) { // Handle any messages from other sub-systems handleIncomingMessage( message ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetTDCommunicationStatus function sets the override * of the TD communication status. * @details \b Inputs: none * @details \b Outputs: tdCommunicationStatus * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testSetTDCommunicationStatus( U32 value ) { BOOL result = FALSE; if (TRUE == isTestingActivated() ) { result = TRUE; tdCommunicationStatus.ovData = value; tdCommunicationStatus.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetTDCommuncationStatus function resets the override * of the TD communication status. * @details \b Inputs: none * @details \b Outputs: tdCommunicationStatus * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetTDCommuncationStatus( void ) { BOOL result = FALSE; if (TRUE == isTestingActivated() ) { result = TRUE; tdCommunicationStatus.override = OVERRIDE_RESET; tdCommunicationStatus.ovData = tdCommunicationStatus.ovInitData; } return result; } /**@}*/