Index: RTC.c =================================================================== diff -u -r88f02ec7299938cc99d60c357f663b88a82da91a -r17fdefc3752a193c0d2d495f1497cc8c1e35c406 --- RTC.c (.../RTC.c) (revision 88f02ec7299938cc99d60c357f663b88a82da91a) +++ RTC.c (.../RTC.c) (revision 17fdefc3752a193c0d2d495f1497cc8c1e35c406) @@ -1,24 +1,28 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 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 +* @file RTC.c * -* @author (last) Sean Nash -* @date (last) 01-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 09-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 11-Jan-2020 +* @author (original) Dara Navaei +* @date (original) 11-Jan-2020 * ***************************************************************************/ #include "mibspi.h" + +#include "FPGA.h" +#include "MessageSupport.h" #include "OperationModes.h" #include "RTC.h" #include "SystemCommMessages.h" #include "Timers.h" +#include "Utilities.h" #ifdef USE_LIBRARY_TIME_FUNCTIONS #include // For epoch conversion functions mktime and gmtime @@ -45,6 +49,8 @@ #define RTC_REG_3_BF_MASK 0x0008 ///< Battery status interrupt flag (0x0008) #define RTC_REG_3_BLF_MASK 0x0004 ///< Battery status low flag (0x0004) +#define RTC_STOP_CLK_COMMAND 0x0020 ///< RTC stop clock command. + // Indices used to check values read from RTC #define RTC_REG_1_INDEX 1U ///< RTC control register 1 index #define RTC_REG_2_INDEX 2U ///< RTC control register 2 index @@ -105,8 +111,8 @@ #define RTC_WRITE_TO_RAM 0x003C ///< RTC write to RAM command (0x003C) #define RTC_READ_FROM_RAM 0x00BD ///< RTC read from RAM command (0x00BD) -#define RTC_ACCURACY_TIMEOUT 1050U ///< RTC accuracy timeout in ms (1050) // TODO - fix test so expecting 1000 ms -#define RTC_ACCURACY_TIMEOUT_TOLERANCE 50U ///< RTC accuracy timeout tolerance in ms (1050) +#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 TIMER_COUNTER_TO_REQUEST_READ 18U ///< Timer counter for reading time from RTC (18) @@ -144,7 +150,6 @@ RTC_SELF_TEST_STATE_START = 0, ///< Self test start RTC_SELF_TEST_STATE_CHECK_CTRL_REGS, ///< Self test check control registers RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND, ///< Self test wait for first second - RTC_SELF_TEST_STATE_WAIT_FOR_SECOND_SECOND, ///< Self test wait for second second RTC_SELF_TEST_STATE_CHECK_ACCURACY, ///< Self test check time accuracy (compare 1st to 2nd second vs. timer counter) RTC_SELF_TEST_STATE_COMPLETE, ///< Self test complete NUM_OF_RTC_SELF_TEST_STATES ///< Total number of self-test states @@ -200,7 +205,7 @@ static U32 RTCSelfTestTimer = 0; ///< Self test timer. static U32 RTCPreviousSecond = 0; ///< Previous second for self-test comparison. static U32 RAMBufferLength = 0; ///< RAM buffer length for RAM operations. -static U32 lastEpochTime = 0; ///< last epoch time. +static U32 lastEpochTime = 0; ///< Last epoch time. static U32 previousTransferLength = 0; ///< Previous transfer length. static U32 timeCounter = 1; ///< Initial time counter (1). @@ -218,6 +223,7 @@ 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 = 0; ///< Previous FPGA timer count; /// Array of days in each month. Assumes non-leap year. Must adjust days in February if leap year. static U32 daysInMonth[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -227,7 +233,7 @@ static BOOL isRTCFunctional( void ); static U08 convertBCD2Decimal( U08 bcd ); static U08 convertDecimal2BCD( U08 decimal ); -static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ); +static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ); static BOOL convertEpoch2DateTime( U32 epoch ); #ifdef USE_LIBRARY_TIME_FUNCTIONS static U32 convertTime2Epoch( void ); @@ -240,7 +246,6 @@ static RTC_SELF_TEST_STATE_T handleSelfTestStart( void ); static RTC_SELF_TEST_STATE_T handleSelfTestCheckCtrlRegs( void ); static RTC_SELF_TEST_STATE_T handleSelfTestWaitForFirstSecond( void ); -static RTC_SELF_TEST_STATE_T handleSelfTestWaitForSecondSecond( void ); static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy( void ); static RTC_EXEC_STATE_T handleExecWaitForPostState( void ); @@ -254,7 +259,7 @@ /*********************************************************************//** * @brief * The initRTC initializes the RTC module. - * @details Inputs: RTCSelfTestState, RTCSelfTestState + * @details Inputs: none * @details Outputs: RTCSelfTestState, RTCSelfTestState * @return none *************************************************************************/ @@ -308,8 +313,8 @@ } else { - hasWriteToRTCRequested = TRUE; - isTimestampBufferReady = FALSE; + hasWriteToRTCRequested = TRUE; + isTimestampBufferReady = FALSE; RTCNewTimestampStruct.seconds = secs; RTCNewTimestampStruct.minutes = mins; RTCNewTimestampStruct.hours = hours; @@ -372,10 +377,6 @@ RTCSelfTestState = handleSelfTestWaitForFirstSecond(); break; - case RTC_SELF_TEST_STATE_WAIT_FOR_SECOND_SECOND: - RTCSelfTestState = handleSelfTestWaitForSecondSecond(); - break; - case RTC_SELF_TEST_STATE_CHECK_ACCURACY: RTCSelfTestState = handleSelfTestCheckAccuracy(); break; @@ -501,8 +502,6 @@ hasWriteToRAMRequested = TRUE; RAMBufferLength = length; prepRAMBuffer [ RTC_PREP_RAM_INDEX ] = RTC_PREP_RAM_READ_WRITE; - //prepRAMBuffer[ RTC_RAM_HIGH_ADDRESS_INDEX ] = ( address >> SHIFT_8_BITS_FOR_BYTE_SHIFT ); - //prepRAMBuffer[ RTC_RAM_LOW_ADDRESS_INDEX ] = ( address & MASK_OFF_MSB ); prepRAMBuffer [ RTC_RAM_HIGH_ADDRESS_INDEX ] = 0x0000; prepRAMBuffer [ RTC_RAM_LOW_ADDRESS_INDEX ] = castedAddress; txBuffer [ BUFFER_INDEX_0 ] = RTC_WRITE_TO_RAM; @@ -563,6 +562,7 @@ } } } + return status; } @@ -726,8 +726,8 @@ *************************************************************************/ static BOOL isRTCFunctional( void ) { -#ifndef DISABLE_RTC_CONFIG BOOL hasTestPassed = TRUE; +#ifndef DISABLE_RTC_CONFIG U16 controlReg1 = rxBuffer[ RTC_REG_1_INDEX ]; U16 controlReg2 = rxBuffer[ RTC_REG_2_INDEX ]; U16 controlReg3 = rxBuffer[ RTC_REG_3_INDEX ]; @@ -773,9 +773,8 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_BATTERY_LOW, controlReg3, RTC_REG_3_BLF_MASK ); hasTestPassed = FALSE; } - - return hasTestPassed; #endif + return hasTestPassed; } /*********************************************************************//** @@ -830,6 +829,7 @@ decimalLow = decimal % TEN; bcd = ( decimalHigh << SHIFT_BITS_BY_4 ) + decimalLow; } + return bcd; } @@ -1111,14 +1111,12 @@ { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WAIT_FOR_POST; -#ifndef DONT_SKIP_NV_POST if ( RTCSelfTestState == RTC_SELF_TEST_STATE_COMPLETE ) { - result = RTC_EXEC_STATE_IDLE; + // After POST is finished, first read the current time so there is one time stamp + // available in the memory + result = RTC_EXEC_STATE_READ; } -#else - result = RTC_EXEC_STATE_IDLE; -#endif return result; } @@ -1137,19 +1135,19 @@ { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_IDLE; - if ( hasWriteToRTCRequested ) + if ( TRUE == hasWriteToRTCRequested ) { result = RTC_EXEC_STATE_WRITE; } - else if ( hasWriteToRAMRequested ) + else if ( TRUE == hasWriteToRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } - else if ( hasReadFromRAMRequested ) + else if ( TRUE == hasReadFromRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } - else if ( timeCounter == TIMER_COUNTER_TO_REQUEST_READ ) + else if ( TIMER_COUNTER_TO_REQUEST_READ == timeCounter ) { prepBufferForReadCommand( RTC_GENERAL_BUFFER_LENGTH ); result = RTC_EXEC_STATE_READ; @@ -1173,7 +1171,7 @@ *************************************************************************/ static RTC_EXEC_STATE_T handleExecWriteState( void ) { - if ( !isTimestampBufferReady ) + if ( FALSE == isTimestampBufferReady ) { txBuffer[ 0 ] = RTC_WRITE_TO_REG0; txBuffer[ 1 ] = 0x0000; @@ -1323,14 +1321,24 @@ { if ( isRTCFunctional() ) { + RTC_DATA_T data; + updateReadTimestampStruct(); #ifndef USE_LIBRARY_TIME_FUNCTIONS lastEpochTime = convertDateTime2Epoch( RTCTimestampStruct ); #else lastEpochTime = convertTime2Epoch(); #endif timeCounter = 1; - broadcastRTCEpoch( lastEpochTime ); + data.epochTime = lastEpochTime; + +#ifdef _DG_ + broadcastData( MSG_ID_RTC_EPOCH, 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 ) ); +#endif } result = RTC_EXEC_STATE_IDLE; @@ -1378,9 +1386,9 @@ RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); - if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { - if ( isRTCFunctional() ) + if ( TRUE == isRTCFunctional() ) { U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; RTCPreviousSecond = RTCCurrentSecond; @@ -1416,57 +1424,17 @@ RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); - if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { - if ( isRTCFunctional() ) + if ( TRUE == isRTCFunctional() ) { U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; if ( RTCCurrentSecond != RTCPreviousSecond ) { RTCPreviousSecond = RTCCurrentSecond; + previousFPGATimerCount = getFPGATimerCount(); RTCSelfTestTimer = getMSTimerCount(); - - result = RTC_SELF_TEST_STATE_WAIT_FOR_SECOND_SECOND; - } - } - else - { - RTCSelfTestResult = SELF_TEST_STATUS_FAILED; - result = RTC_SELF_TEST_STATE_COMPLETE; - } - } - else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) - { - RTCSelfTestResult = SELF_TEST_STATUS_FAILED; - result = RTC_SELF_TEST_STATE_COMPLETE; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSelfTestWaitForSecondSecond continuously reads the RTC and compares - * latest second from RTC to the previous second and if it has changed, it will - * set the state machine to the next state. - * @details Inputs: RTCServiceState, txBuffer, rxBuffer, RTCCurrentSecond - * @details Outputs: RTCCurrentSecond - * @return next state - *************************************************************************/ -static RTC_SELF_TEST_STATE_T handleSelfTestWaitForSecondSecond( void ) -{ - RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_WAIT_FOR_SECOND_SECOND; - BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); - - if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) // TODO - should probably have a timeout on these waits - { - if ( isRTCFunctional() ) - { - U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; - - if ( RTCCurrentSecond != RTCPreviousSecond ) - { result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; } } @@ -1479,7 +1447,7 @@ else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; - result = RTC_SELF_TEST_STATE_COMPLETE; + result = RTC_SELF_TEST_STATE_COMPLETE; } return result; @@ -1499,23 +1467,73 @@ static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy( void ) { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; + BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); - if ( didTimeout( RTCSelfTestTimer, RTC_ACCURACY_TIMEOUT ) ) + if ( ( TRUE == isStatusOk ) && ( rxBuffer[ RTC_SECONDS_INDEX ] != RTCPreviousSecond ) ) { - U32 elapsedTime = calcTimeSince( RTCSelfTestTimer ); - S32 deltaTime = (S32)elapsedTime - (S32)RTC_ACCURACY_TIMEOUT; + S32 const elapsedTime = (S32)calcTimeSince( RTCSelfTestTimer ); + S32 const deltaTime = elapsedTime - (S32)MS_PER_SECOND; + S32 const elapsedFPGATime = (S32)u16DiffWithWrap( previousFPGATimerCount, getFPGATimerCount() ); + result = RTC_SELF_TEST_STATE_COMPLETE; + RTCSelfTestResult = SELF_TEST_STATUS_PASSED; - if ( abs( deltaTime ) > RTC_ACCURACY_TIMEOUT_TOLERANCE ) + if ( abs( deltaTime ) > RTC_ACCURACY_TOLERANCE ) { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_OR_TIMER_ACCURACY_FAILURE, (U32)deltaTime, RTC_ACCURACY_TIMEOUT_TOLERANCE ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_OR_TIMER_ACCURACY_FAILURE, (U32)deltaTime, RTC_ACCURACY_TOLERANCE ); } - else + + if ( abs( elapsedFPGATime - elapsedTime ) > FPGA_ACCURACY_TOLERANCE ) { - RTCSelfTestResult = SELF_TEST_STATUS_PASSED; + RTCSelfTestResult = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RTC_OR_TIMER_ACCURACY_FAILURE, (U32)elapsedFPGATime, (U32)elapsedTime ); } + } - result = RTC_SELF_TEST_STATE_COMPLETE; + return result; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetStopRTC sets the 5th bit of the first control register and + * sets its bit to 1 to stop the RTC clock. + * @details Inputs: none + * @details Outputs: hasWriteToRTCRequested, isTimestampBufferReady, txBuffer + * @return TRUE if the set was successful otherwise, FALSE + *************************************************************************/ +BOOL testSetStopRTC( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Set write request so the exec state machine will set it + hasWriteToRTCRequested = TRUE; + isTimestampBufferReady = TRUE; + + // Set the latest time stamp to be written to the RTC since the stop command must be written + // to RTC anyways + txBuffer[ 0 ] = RTC_WRITE_TO_REG0; + // Read the RX buffer and get the first register. Mask off the MSB and or it with 0x0020 to set the + // start stop RTC bit to a 1 to stop the RTC clock. + txBuffer[ 1 ] = ( rxBuffer[ RTC_REG_1_INDEX ] & MASK_OFF_MSB ) | RTC_STOP_CLK_COMMAND; + txBuffer[ 2 ] = 0x0000; + txBuffer[ 3 ] = 0x0000; + txBuffer[ 4 ] = convertDecimal2BCD( RTCNewTimestampStruct.seconds ); + txBuffer[ 5 ] = convertDecimal2BCD( RTCNewTimestampStruct.minutes ); + txBuffer[ 6 ] = convertDecimal2BCD( RTCNewTimestampStruct.hours ); + txBuffer[ 7 ] = convertDecimal2BCD( RTCNewTimestampStruct.days ); + txBuffer[ 8 ] = convertDecimal2BCD( RTCNewTimestampStruct.weekdays ); // Weekdays will not be used + txBuffer[ 9 ] = convertDecimal2BCD( RTCNewTimestampStruct.months ); + txBuffer[ 10 ] = convertDecimal2BCD( ( RTCNewTimestampStruct.years - YEAR_2000 ) ); + + result = TRUE; } return result;