Index: RTC.c =================================================================== diff -u -rd6b9e2bb9886a4bf7954204710ddb571314b3b06 -r59871c9964559b5137781af9c2eeed6bab18ef73 --- RTC.c (.../RTC.c) (revision d6b9e2bb9886a4bf7954204710ddb571314b3b06) +++ RTC.c (.../RTC.c) (revision 59871c9964559b5137781af9c2eeed6bab18ef73) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-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 RTC.c * -* @author (last) Sean Nash -* @date (last) 18-Aug-2022 +* @author (last) Bill Bracken +* @date (last) 19-Sep-2023 * * @author (original) Dara Navaei * @date (original) 11-Jan-2020 @@ -19,11 +19,14 @@ #include "FPGA.h" #include "MessageSupport.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "RTC.h" #include "SystemCommMessages.h" +#include "TestSupport.h" #include "Timers.h" #include "Utilities.h" + /** * @addtogroup RTC * @{ @@ -110,6 +113,8 @@ #define RTC_ACCURACY_TOLERANCE 75U ///< RTC accuracy tolerance in ms #define FPGA_ACCURACY_TOLERANCE 12U ///< FPGA accuracy tolerance in ms #define RTC_PUBLISH_INTERVAL 18U ///< RTC publish interval in counts (18) +#define RTC_REG_ERROR_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< RTC register error timeout in milliseconds. +#define RTC_BATTERY_LOW_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< RTC battery low timeout in milliseconds. #define TIMER_COUNTER_TO_REQUEST_READ 18U ///< Timer counter for reading time from RTC (18) #define MAX_ALLOWED_FAILED_RTC_TRANSFERS 3U ///< Max allowed failed RTC transfers (3) @@ -205,6 +210,8 @@ static U16 prepRAMBuffer[ RTC_RAM_PREP_BUFFER_LENGTH ]; ///< Buffer to send prep read/write commands to RTC RAM. static U16 RAMBuffer[ MIBSPI_MAX_BUFFER_LENGTH ]; ///< Buffer to read RTC RAM data. static U16 previousFPGATimerCount; ///< Previous FPGA timer count; +static OVERRIDE_U32_T rtcControlRegister1 = { 0, 0, 0, 0 }; ///< RTC control register 1. +static OVERRIDE_U32_T rtcControlRegister3 = { 0, 0, 0, 0 }; ///< RTC control register 3. #ifdef _DG_ static BOOL syncDG2HDDateTimeFlag; ///< Flag indicating whether DG RTC should be sync'd to HD RTC. #endif @@ -223,6 +230,8 @@ static void updateReadTimestampStruct( void ); static BOOL setMibSPIBufferLength( U16 length ); static void prepBufferForReadCommand( U08 length ); // Puts the read command +static U16 getControlReg1( void ); +static U16 getControlReg3( void ); static RTC_SELF_TEST_STATE_T handleSelfTestStart( void ); static RTC_SELF_TEST_STATE_T handleSelfTestCheckCtrlRegs( void ); @@ -268,6 +277,15 @@ #ifdef _DG_ syncDG2HDDateTimeFlag = FALSE; #endif + +#ifdef _DG_ + initPersistentAlarm( ALARM_ID_DG_RTC_CONFIG_ERROR, RTC_REG_ERROR_TIMEOUT_MS, RTC_REG_ERROR_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_RTC_BATTERY_LOW, RTC_BATTERY_LOW_TIMEOUT_MS, RTC_BATTERY_LOW_TIMEOUT_MS ); +#endif +#ifdef _HD_ + initPersistentAlarm( ALARM_ID_HD_RTC_CONFIG_ERROR, RTC_REG_ERROR_TIMEOUT_MS, RTC_REG_ERROR_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_RTC_BATTERY_LOW, RTC_BATTERY_LOW_TIMEOUT_MS, RTC_BATTERY_LOW_TIMEOUT_MS ); +#endif } /*********************************************************************//** @@ -308,10 +326,6 @@ { isDataOk = FALSE; } - else if ( ( years - YEAR_2000 ) > MAX_ALLOWED_YEARS ) - { - isDataOk = FALSE; - } else { hasWriteToRTCRequested = TRUE; @@ -460,6 +474,18 @@ return lastEpochTime; } +/*********************************************************************//** + * @brief + * The resetRTCPOSTState resets the RTC POST state to start. + * @details Inputs: none + * @details Outputs: RTCSelfTestState + * @return none + *************************************************************************/ +void resetRTCPOSTState( void ) +{ + RTCSelfTestState = RTC_SELF_TEST_STATE_START; +} + #ifdef _DG_ /*********************************************************************//** * @brief @@ -761,20 +787,31 @@ *************************************************************************/ static BOOL isRTCFunctional( void ) { - ALARM_ID_T alarm; - BOOL hasTestPassed = TRUE; + ALARM_ID_T reg1Alarm; + ALARM_ID_T batteryAlarm; + BOOL hasReg1Failed = FALSE; + BOOL isBatteryLow = FALSE; + BOOL status = TRUE; + U16 controlReg1 = 0; + U16 controlReg2 = rxBuffer[ RTC_REG_2_INDEX ]; + U16 controlReg3 = 0; + // populate real data before we consider override + rtcControlRegister1.data = rxBuffer[ RTC_REG_1_INDEX ]; + controlReg1 = getControlReg1(); + + rtcControlRegister3.data = rxBuffer[ RTC_REG_3_INDEX ]; + controlReg3 = getControlReg3(); + #ifdef _DG_ - alarm = ALARM_ID_DG_RTC_CONFIG_ERROR; + reg1Alarm = ALARM_ID_DG_RTC_CONFIG_ERROR; + batteryAlarm = ALARM_ID_DG_RTC_BATTERY_LOW; #endif #ifdef _HD_ - alarm = ALARM_ID_HD_RTC_CONFIG_ERROR; + reg1Alarm = ALARM_ID_HD_RTC_CONFIG_ERROR; + batteryAlarm = ALARM_ID_HD_RTC_BATTERY_LOW; #endif - U16 controlReg1 = rxBuffer[ RTC_REG_1_INDEX ]; - U16 controlReg2 = rxBuffer[ RTC_REG_2_INDEX ]; - U16 controlReg3 = rxBuffer[ RTC_REG_3_INDEX ]; - controlReg1 = controlReg1 & MASK_OFF_MSB; controlReg2 = controlReg2 & MASK_OFF_MSB; controlReg3 = controlReg3 & MASK_OFF_MSB; @@ -788,41 +825,35 @@ if ( controlReg1 & RTC_REG_1_12_HOUR_MODE_MASK ) { - SET_ALARM_WITH_2_U32_DATA( alarm, controlReg1, RTC_REG_1_12_HOUR_MODE_MASK ); - hasTestPassed = FALSE; + hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_PORO ) { - SET_ALARM_WITH_2_U32_DATA( alarm, controlReg1, RTC_REG_1_PORO ); - hasTestPassed = FALSE; + hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_CLK_STOPPED_MASK ) { - SET_ALARM_WITH_2_U32_DATA( alarm, controlReg1, RTC_REG_1_CLK_STOPPED_MASK ); - hasTestPassed = FALSE; + hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_UNUSED_MASK ) { - SET_ALARM_WITH_2_U32_DATA( alarm, controlReg1, RTC_REG_1_UNUSED_MASK ); - hasTestPassed = FALSE; + hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_EXT_CLK_MODE_MASK ) { - SET_ALARM_WITH_2_U32_DATA( alarm, controlReg1, RTC_REG_1_EXT_CLK_MODE_MASK ); - hasTestPassed = FALSE; + hasReg1Failed = TRUE; } if ( controlReg3 & RTC_REG_3_BLF_MASK ) { -#ifdef _DG_ - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_RTC_BATTERY_LOW, controlReg3, RTC_REG_3_BLF_MASK ); -#endif -#ifdef _HD_ - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_RTC_BATTERY_LOW, controlReg3, RTC_REG_3_BLF_MASK ); -#endif - hasTestPassed = FALSE; + isBatteryLow = TRUE; } - return hasTestPassed; + status = ( ( FALSE == hasReg1Failed ) && ( FALSE == isBatteryLow ) ? TRUE : FALSE ); + + checkPersistentAlarm( reg1Alarm, hasReg1Failed, controlReg1, 0 ); + checkPersistentAlarm( batteryAlarm, isBatteryLow, controlReg3, 0 ); + + return status; } /*********************************************************************//** @@ -1165,9 +1196,13 @@ else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); - - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_RTC_RAM_OPS_ERROR, result ); - result = RTC_EXEC_STATE_IDLE; +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif +#ifdef _HD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif + result = RTC_EXEC_STATE_IDLE; hasWriteToRTCRequested = FALSE; } @@ -1201,8 +1236,12 @@ else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); - - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_RTC_RAM_OPS_ERROR, result ); +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif +#ifdef _HD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif result = RTC_EXEC_STATE_IDLE; } @@ -1236,8 +1275,13 @@ releaseSemaphore( SEMAPHORE_RTC ); RTCRAMStatus = RTC_RAM_STATUS_FAILED; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_RAM_OPS_ERROR, result, RTCRAMStatus ); - result = RTC_EXEC_STATE_IDLE; +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif +#ifdef _HD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif + result = RTC_EXEC_STATE_IDLE; hasWriteToRAMRequested = FALSE; } @@ -1271,8 +1315,13 @@ releaseSemaphore( SEMAPHORE_RTC ); RTCRAMStatus = RTC_RAM_STATUS_FAILED; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_RAM_OPS_ERROR, result, RTCRAMStatus ); - result = RTC_EXEC_STATE_IDLE; +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif +#ifdef _HD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif + result = RTC_EXEC_STATE_IDLE; hasReadFromRAMRequested = FALSE; } @@ -1306,11 +1355,10 @@ data.epochTime = lastEpochTime; #ifdef _DG_ - broadcastData( MSG_ID_DG_RTC_EPOCH, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( RTC_DATA_T ) ); + broadcastData( MSG_ID_DG_RTC_EPOCH_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( RTC_DATA_T ) ); #endif - #ifdef _HD_ - broadcastData( MSG_ID_RTC_EPOCH, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( RTC_DATA_T ) ); + broadcastData( MSG_ID_RTC_EPOCH_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( RTC_DATA_T ) ); #endif } @@ -1321,8 +1369,12 @@ else if ( RTC_SERVICE_COMPLETE == RTCServiceState ) { releaseSemaphore( SEMAPHORE_RTC ); - - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_RTC_RAM_OPS_ERROR, result ); +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif +#ifdef _HD_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, result ) +#endif result = RTC_EXEC_STATE_IDLE; } @@ -1465,7 +1517,6 @@ ALARM_ID_T alarm; S32 elapsedTime = (S32)calcTimeSince( RTCSelfTestTimer ); - S32 deltaTime = elapsedTime - (S32)MS_PER_SECOND; S32 elapsedFPGATime = (S32)u16DiffWithWrap( previousFPGATimerCount, getFPGATimerCount() ); result = RTC_SELF_TEST_STATE_CHECK_RTC_YEAR; @@ -1476,13 +1527,6 @@ alarm = ALARM_ID_HD_RTC_OR_TIMER_ACCURACY_FAILURE; #endif - if ( abs( deltaTime ) > RTC_ACCURACY_TOLERANCE ) - { - RTCSelfTestResult = SELF_TEST_STATUS_FAILED; - result = RTC_SELF_TEST_STATE_COMPLETE; - SET_ALARM_WITH_2_U32_DATA( alarm, (U32)deltaTime, RTC_ACCURACY_TOLERANCE ); - } - if ( abs( elapsedFPGATime - elapsedTime ) > FPGA_ACCURACY_TOLERANCE ) { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; @@ -1501,7 +1545,7 @@ * The handleSelfTestCheckRTCYear checks whether the year that has been set * in RTC is greater than 2021 or not. * @details Inputs: RTCSelfTestTimer - * Outputs : RTCSelfTestResult + * @details Outputs: RTCSelfTestResult * @return next state *************************************************************************/ static RTC_SELF_TEST_STATE_T handleSelfTestCheckRTCYear( void ) @@ -1531,7 +1575,31 @@ return state; } +/*********************************************************************//** + * @brief + * The getControlReg1 function gets the current RTC control register 1. + * @details Inputs: rtcControlRegister1 + * @details Outputs: none + * @return the current RTC control register word. + *************************************************************************/ +static U16 getControlReg1( void ) +{ + return getU16OverrideValue(&rtcControlRegister1); +} +/*********************************************************************//** + * @brief + * The getControlReg3 function gets the current RTC control register 3. + * @details Inputs: rtcControlRegister3 + * @details Outputs: none + * @return the current RTC control register word. + *************************************************************************/ +static U16 getControlReg3( void ) +{ + return getU16OverrideValue(&rtcControlRegister3); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -1577,4 +1645,92 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetRTCCtlReg1Status function overrides RTC control register 1 + * @details Inputs: none + * @details Outputs: rtcControlRegister1 + * @param status override RTC control register 1 with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetRTCCtlReg1Status( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rtcControlRegister1.ovData = status; + rtcControlRegister1.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetRTCCtlReg1Status function resets the override + * of RTC control register 1. + * @details Inputs: none + * @details Outputs: rtcControlRegister1 + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetRTCCtlReg1Status( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rtcControlRegister1.override = OVERRIDE_RESET; + rtcControlRegister1.ovData = rtcControlRegister1.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetRTCCtlReg3Status function overrides RTC control register 3 + * @details Inputs: none + * @details Outputs: rtcControlRegister1 + * @param status override RTC control register 1 with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetRTCCtlReg3Status( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rtcControlRegister3.ovData = status; + rtcControlRegister3.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetRTCCtlReg3Status function resets the override + * of RTC control register 3. + * @details Inputs: none + * @details Outputs: rtcControlRegister1 + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetRTCCtlReg3Status( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rtcControlRegister3.override = OVERRIDE_RESET; + rtcControlRegister3.ovData = rtcControlRegister1.ovInitData; + } + + return result; +} + /**@}*/