/************************************************************************** * * 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 AlarmMgmt.c * * @author (last) Sean * @date (last) 30-Jul-2024 * * @author (original) Sean * @date (original) 30-Jul-2024 * ***************************************************************************/ #include "mibspi.h" #define __ALARM_MGMT_C__ #ifdef _RO_ #include "FPOperationModes.h" #else #include "OperationModes.h" #endif #include "Messaging.h" #include "TaskGeneral.h" #include "Timers.h" /** * @addtogroup AlarmManagement * @{ */ // ********** private definitions ********** // *** This declaration will cause a compiler error if ALARM_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmTableSizeAssertion[ ( ( sizeof( ALARM_TABLE ) / sizeof( ALARM_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; // *** This declaration will cause a compiler error if ALARM_RANK_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmRankTableSizeAssertion[ ( ( sizeof( ALARM_RANK_TABLE ) / sizeof( ALARM_RANK_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; // ********** private data ********** static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm static BOOL alarmIsDetected[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm condition (detected or cleared) // ********** private function prototypes ********** /*********************************************************************//** * @brief * The initAlarmMgmt function initializes the AlarmMgmt unit. * @details \b Inputs: none * @details \b Outputs: alarmIsActive[], alarmIsDetected[] * @return none *************************************************************************/ void initAlarmMgmt( void ) { ALARM_ID_T a; // Initialize alarm states and start time stamps for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { alarmIsActive[ a ] = FALSE; alarmIsDetected[ a ] = FALSE; } } /*********************************************************************//** * @brief * The getAlarmProperties function gets the alarm properties for a given alarm. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm invalid. * @details \b Inputs: ALARM_TABLE[] * @details \b Outputs: none * @param alarm ID of alarm to get the properties record for * @return properties record for given alarm *************************************************************************/ ALARM_T getAlarmProperties( ALARM_ID_T alarm ) { ALARM_T result = ALARM_TABLE[ ALARM_ID_NO_ALARM ]; if ( alarm < NUM_OF_ALARM_IDS ) { result = ALARM_TABLE[ alarm ]; } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_PROPS, (U32)alarm ) #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_PROPS, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_PROPS, (U32)alarm ) #endif } return result; } /*********************************************************************//** * @brief * The getAlarmRank function gets the alarm rank for a given alarm index. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm index is invalid. * @details \b Inputs: ALARM_RANK_TABLE[] * @details \b Outputs: none * @param index index to alarm rank table (lower index = lower rank number = higher rank) * @return Alarm rank record for given alarm index *************************************************************************/ ALARM_RANK_T getAlarmRank( U32 index ) { ALARM_RANK_T result = ALARM_RANK_TABLE[ 0 ]; if ( index < NUM_OF_ALARM_IDS ) { result = ALARM_RANK_TABLE[ index ]; } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_RANK, index ); #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_RANK, index ); #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_GET_RANK, index ); #endif } return result; } /*********************************************************************//** * @brief * The activateAlarm function activates a given alarm. * @details \b Alarm: Given alarm is activated if not already. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm ID is invalid. * @details \b Inputs: alarmIsActive[], alarmIsDetected[], ALARM_TABLE[] * @details \b Outputs: alarmIsActive[], alarmStartedAt[], alarmStatus is updated * @param alarm ID of alarm to activate * @return none *************************************************************************/ void activateAlarm( ALARM_ID_T alarm ) { // Verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm if ( ( FALSE == alarmIsActive[ alarm ] ) || ( ( FALSE == alarmIsDetected[ alarm ] ) && ( FALSE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) ) ) { // Activate alarm alarmIsActive[ alarm ] = TRUE; alarmIsDetected[ alarm ] = TRUE; // If alarm has clear condition immediately property, clear condition now if ( TRUE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) { clearAlarmCondition( alarm ); } } } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE3, (U32)alarm ) #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE3, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE3, (U32)alarm ) #endif } } /*********************************************************************//** * @brief * The clearAlarmCondition function clears a given alarm's condition detected * flag. Also an alarm message is broadcast to the rest of the system. * @details \b Message \b Sent: MSG_ID_ALARM_CONDITION_CLEARED if alarm condition cleared. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm ID invalid. * @details \b Inputs: alarmIsDetected[] * @details \b Outputs: alarmIsDetected[] * @param alarm ID of alarm to clear condition for * @return none *************************************************************************/ void clearAlarmCondition( ALARM_ID_T alarm ) { // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // Clear alarm condition and broadcast alarm condition clear if not already cleared if ( TRUE == alarmIsDetected[ alarm ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32)alarm; alarmIsDetected[ alarm ] = FALSE; #ifdef _TD_ broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_TD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif #ifdef _DD_ broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_DD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif #ifdef _RO_ broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_FP_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif } } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR_COND, (U32)alarm ) #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR_COND, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR_COND, (U32)alarm ) #endif } } /*********************************************************************//** * @brief * The clearAlarm function clears a given alarm if it is recoverable. Also * an alarm message is broadcast to the rest of the system. * @details \b Message \b Sent: MSG_ID_ALARM_CLEARED if alarm cleared. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm ID invalid. * @details \b Inputs: ALARM_TABLE[], alarmIsActive[] * @details \b Outputs: alarmIsActive[] * @param alarm ID of alarm to clear * @return none *************************************************************************/ void clearAlarm( ALARM_ID_T alarm ) { // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // Verify alarm can be cleared if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) { // Clear alarm and broadcast alarm clear if not already cleared if ( TRUE == alarmIsActive[ alarm ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32) alarm; alarmIsActive[ alarm ] = FALSE; clearAlarmCondition( alarm ); #ifdef _TD_ broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_TD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif #ifdef _DD_ broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_DD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif #ifdef _RO_ broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_FP_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); #endif } } } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR2, (U32)alarm ) #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR2, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR2, (U32)alarm ) #endif } } /*********************************************************************//** * @brief * The setAlarmActive function sets the active flag for a given alarm. * @details \b Inputs: none * @details \b Outputs: alarmIsActive[] * @param alarm ID of alarm to set active flag for * @param active TRUE if setting alarm as active, FALSE if setting alarm as inactive * @return none *************************************************************************/ void setAlarmActive( ALARM_ID_T alarm, BOOL active ) { alarmIsActive[ alarm ] = active; } /*********************************************************************//** * @brief * The setAlarmConditionDetected function sets the condition detected flag * for a given alarm. * @details \b Inputs: none * @details \b Outputs: alarmIsDetected[] * @param alarm ID of alarm to set condition detected flag for * @param detected TRUE if setting alarm condition as detected, FALSE if * setting alarm condition as not detected * @return none *************************************************************************/ void setAlarmConditionDetected( ALARM_ID_T alarm, BOOL detected ) { alarmIsDetected[ alarm ] = detected; } /*********************************************************************//** * @brief * The isAlarmActive function determines whether a given alarm is currently * active. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm ID is invalid. * @details \b Inputs: alarmIsActive[] * @details \b Outputs: none * @param alarm ID of alarm to check active status for * @return TRUE if given alarm is active, FALSE if not *************************************************************************/ BOOL isAlarmActive( ALARM_ID_T alarm ) { BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) { result = alarmIsActive[ alarm ]; } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED1, (U32)alarm ); #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED1, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED1, (U32)alarm ) #endif } return result; } /*********************************************************************//** * @brief * The isAlarmConditionDetected function determines whether a given alarm * condition is currently detected. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given alarm ID is invalid. * @details \b Inputs: alarmIsDetected[] * @details \b Outputs: none * @param alarm ID of alarm to check alarm condition detected status for * @return TRUE if alarm condition for given alarm is detected, FALSE if not *************************************************************************/ BOOL isAlarmConditionDetected( ALARM_ID_T alarm ) { BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) { if ( ( TRUE == alarmIsActive[ alarm ] ) && ( TRUE == alarmIsDetected[ alarm ] ) ) { result = TRUE; } } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED2, (U32)alarm ); #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED2, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED2, (U32)alarm ) #endif } return result; } /*********************************************************************//** * @brief * The isAlarmRecoverable function determines whether a given alarm is * recoverable. * @details \b Alarm: ALARM_ID_XX_SOFTWARE_FAULT if given alarm ID invalid. * @details \b Inputs: ALARM_TABLE[] * @details \b Outputs: none * @param alarm ID of alarm to determine recoverable status for * @return TRUE if given alarm is recoverable, FALSE if not *************************************************************************/ BOOL isAlarmRecoverable( ALARM_ID_T alarm ) { BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) { result = ( TRUE == ALARM_TABLE[ alarm ].alarmNoClear ? FALSE : TRUE ); } else { #ifdef _TD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED3, (U32)alarm ); #endif #ifdef _DD_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED3, (U32)alarm ) #endif #ifdef _RO_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED3, (U32)alarm ) #endif } return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testAlarmStateOverride function overrides the state of the * alarm active state for a given alarm with the alarm management with * a given active state. * @details \b Inputs: none * @details \b Outputs: alarm activated or cleared * @param message Override message from Dialin which includes an ID of * the alarm to override and the state to override the alarm to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testAlarmStateOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); // Verify tester has logged in with f/w and override type is valid if ( ( TRUE == isTestingActivated() ) && ( ovType != OVERRIDE_INVALID ) && ( ovType < NUM_OF_OVERRIDE_TYPES ) ) { U32 alarmID = payload.index; BOOL state = (BOOL)payload.state.u32; if ( alarmID < NUM_OF_ALARM_IDS ) { if ( TRUE == state ) { activateAlarmNoData( (ALARM_ID_T)alarmID ); } else { #ifdef _TD_ clearAlarmTD( (ALARM_ID_T)alarmID ); #endif #ifdef _DD_ clearAlarmDD( (ALARM_ID_T)alarmID ); #endif #ifdef _RO_ clearAlarmFP( (ALARM_ID_T)alarmID ); #endif } result = TRUE; } } return result; } /**@}*/