/************************************************************************** * * Copyright (c) 2020-2023 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) Michael Garthwaite * @date (last) 01-Mar-2023 * * @author (original) Dara Navaei * @date (original) 11-Jan-2020 * ***************************************************************************/ #include "mibspi.h" #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 * @{ */ // ********** Definitions ********** #define RTC_REG_1_12_HOUR_MODE_MASK 0x0004 ///< 12-hour mode mask (0x0004) #define RTC_REG_1_PORO 0x0008 ///< Power On Reset Override (0x0008) #define RTC_REG_1_CLK_STOPPED_MASK 0x0020 ///< RTC source clock mask (0x0020) #define RTC_REG_1_UNUSED_MASK 0x0040 ///< Unused mask (0x0040) #define RTC_REG_1_EXT_CLK_MODE_MASK 0x0080 ///< RTC external clock test mode mask (0x0080) #define RTC_REG_2_MSF_MASK 0x0080 ///< Minute or second interrupt mask (0x0080) #define RTC_REG_2_CDTF_MASK 0x0008 ///< Countdown timer interrupt mask (0x0008) #define RTC_REG_2_AF_MASK 0x0010 ///< Alarm interrupt mask (0x0010) #define RTC_REG_2_TSF2_MASK 0x0020 ///< Timestamp interrupt mask (0x0020) #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 #define RTC_REG_3_INDEX 3U ///< RTC control register 3 index #define RTC_SECONDS_INDEX 4U ///< RTC seconds index #define RTC_MINUTES_INDEX 5U ///< RTC minutes index #define RTC_HOURS_INDEX 6U ///< RTC hours index #define RTC_DAYS_INDEX 7U ///< RTC days index #define RTC_WEEKDAYS_INDEX 8U ///< RTC weekdays index #define RTC_MONTHS_INDEX 9U ///< RTC months index #define RTC_YEARS_INDEX 10U ///< RTC years index // Time and date acceptable ranges #define MAX_ALLOWED_SECONDS 59U ///< Max allowed seconds (59) #define MAX_ALLOWED_MINUTES 59U ///< Max allowed minutes (59) #define MAX_ALLWOED_HOURS 23U ///< Max allowed hours (23) #define MAX_ALLOWED_DAYS 31U ///< Max allowed days (31) #define MIN_ALLOWED_DAYS 1U ///< Min allowed days (1) #define MAX_ALLOWED_MONTHS 12U ///< Max allowed months (12) #define MIN_ALLOWED_MONTHS 1U ///< Min allowed months (1) #define MAX_ALLOWED_YEARS 99U ///< Max allowed years (99) #define BUFFER_INDEX_0 0U ///< Buffer index 0 #define BUFFER_INDEX_1 1U ///< Buffer index 1 #define BUFFER_INDEX_2 2U ///< Buffer index 2 #define BUFFER_INDEX_3 3U ///< Buffer index 3 #define BUFFER_INDEX_4 4U ///< Buffer index 4 #define MIBSPI_MAX_BUFFER_LENGTH 127U ///< MibSPI max buffer length (127) #define MIBSPI_CONTINUOUS_MODE 4U ///< MibSPI continuous mode (4) #define MIBSPI_CHIP_SELECT_ACTIVE 1U ///< MibSPI chip select active (1) #define MIBSPI_CHIP_SELECT_DEACTIVE 0U ///< MibSPI chip select deactive (0) #define MIBSPI_NO_WDELAY 0U ///< MibSPI no wdelay (0) #define MIBSPI_LOCK_TG 0U ///< MibSPI lock TG (0) #define MIBSPI_DATA_FORMAT_ZERO 0U ///< MibSPI data format zero (0) #define MIBSPI_GROUP_ZERO 0U ///< MibSPI group zero (0) #define MIBSPI_BUFFER_MODE_BIT_SHIFT_13 13U ///< MibSPI buffer mode bit shift by 13 (13) #define MIBSPI_CHIP_SELECT_BIT_SHIFT_12 12U ///< MibSPI chip select big shift by 12 (12) #define MIBSPI_NO_WDELAY_BIT_SHIFT_10 10U ///< MibSPI no wdelay bit shift by 10 (10) #define MIBSPI_LOCK_TRANS_BIT_SHIFT_11 11U ///< MibSPI lock trans bit shift by 11 (11) #define MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT_8 8U ///< MibSPI data format zero bit shift by 8 (8) #define MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 8U ///< MibSPI tran but shift by 8 (8) #define RTC_RAM_PREP_BUFFER_LENGTH 3U ///< RTC RAM prep buffer length (3) #define RTC_TIMESTAMP_BUFFER_LENGTH 8U ///< RTC RAM timestamp buffer length (8) #define RTC_GENERAL_BUFFER_LENGTH 11U ///< RTC general buffer length (11) #define RTC_PREP_RAM_INDEX 0U ///< RTC prep RAM index (0) #define RTC_RAM_HIGH_ADDRESS_INDEX 1U ///< RTC RAM high address index (1) #define RTC_RAM_LOW_ADDRESS_INDEX 2U ///< RTC RAM low address index (2) #define RTC_RAM_COMMAND_INDEX 3U ///< RTC RAM command index (3) #define RTC_READ_FROM_REG0 0x00A0 ///< Read from RTC register0 (0x00A0) #define RTC_WRITE_TO_REG3 0x0023 ///< Write to RTC from seconds register (0x0023) #define RTC_WRITE_TO_REG0 0x0020 ///< Write to RTC from register0 (0x0020) #define RTC_PREP_RAM_READ_WRITE 0x003A ///< RTC RAM command for read or write (0x003A) #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_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 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) #define MAX_ALLOWED_RTC_RAM_BYTES 100U ///< Max allowed RTC RAM bytes to be accepted from a caller (100) #define MAX_ALLOWED_RTC_RAM_ADDRESS 512U ///< Max allowed RTC RAM legal address (512) #define TEN 10U ///< Ten #define YEAR_2000 2000U ///< Year 2000 #define EPOCH_BASE_YEAR 1970U ///< Reference year to calculate epoch (1970) #define YEAR_2021 2021U ///< Year 2021 #define SECS_IN_HOUR 3600 ///< Number of seconds in an hour. #define MONTHS_IN_YEAR 12 ///< Number of months in a year. #define LEAP_YEAR_MONTH ( 2 - 1 ) ///< Leap year month is February. Subtract 1 month for zero-based months. #define SECONDS_IN_NORMAL_YEAR ( SECONDS_IN_A_DAY * 365 ) ///< Number of seconds in a normal year. #define SECONDS_IN_LEAP_YEAR ( SECONDS_IN_A_DAY * 366 ) ///< Number of seconds in a leap year. #define DAYS_IN_NORMAL_YEAR (365) ///< Number of days in a normal year. #define DAYS_IN_LEAP_YEAR (366) ///< Number of days in a leap year. /// Number of seconds in 4 years. Includes an extra day for 1 leap within any 4 year period. static const U32 SECONDS_IN_4_YEARS = SECONDS_IN_NORMAL_YEAR * 3 + SECONDS_IN_LEAP_YEAR; /// Number of seconds in 2 years. Assumes no leap year in 2 year period. static const U32 SECONDS_IN_2_YEARS = SECONDS_IN_NORMAL_YEAR * 2; #define MIN_EPOCH_DATE ( 1689958503 ) ///< Epoch dates must be greater than 8/11/2023 /// RTC self-test state enumeration. typedef enum RTC_Self_Test_States { 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_CHECK_ACCURACY, ///< Self test check time accuracy (compare 1st to 2nd second vs. timer counter) RTC_SELF_TEST_STATE_CHECK_RTC_YEAR, ///< Self test check RTC year RTC_SELF_TEST_STATE_COMPLETE, ///< Self test complete NUM_OF_RTC_SELF_TEST_STATES ///< Total number of self-test states } RTC_SELF_TEST_STATE_T; /// Read date states enumeration. typedef enum RTC_Read_Data { RTC_SEND_COMMAND = 0, ///< RTC send command RTC_WAIT_FOR_TRANSFER_AND_READ, ///< RTC wait for transfer and read RTC_SERVICE_COMPLETE, ///< RTC service complete NUM_OF_RTC_SERVICE_STATES ///< Total number of RTC read date states } RTC_GET_DATA_STATE_T; /// RTC exec state enumeration. typedef enum RTC_Exec_State { RTC_EXEC_STATE_WAIT_FOR_POST = 0, ///< Exec state wait for post RTC_EXEC_STATE_IDLE, ///< Exec state idle RTC_EXEC_STATE_PREP_RAM, ///< Exec state prep RAM RTC_EXEC_STATE_WRITE_TO_RAM, ///< Exec state write to RAM RTC_EXEC_STATE_READ_FROM_RAM, ///< Exec state read from RAM RTC_EXEC_STATE_READ, ///< Exec state read RTC_EXEC_STATE_WRITE, ///< Exec state write RTC_EXEC_STATE_VERIFY_WRITE, ///< Exec state verify RTC write NUM_OF_RTC_EXEC_STATES ///< Total number of exec states } RTC_EXEC_STATE_T; #pragma pack(push,4) /// Timestamp structure. typedef struct { U16 seconds; ///< Seconds U16 minutes; ///< Minutes U16 hours; ///< Hours U16 days; ///< Days U16 weekdays; ///< Weekdays U16 months; ///< Months U16 years; ///< Years } RTC_TIMESTAMP_T; #pragma pack(pop) // ********** private data ********** static RTC_SELF_TEST_STATE_T RTCSelfTestState; ///< Self test variable. static RTC_GET_DATA_STATE_T RTCServiceState; ///< RTC get data variable. static RTC_EXEC_STATE_T RTCExecState; ///< RTC exec state variable. static SELF_TEST_STATUS_T RTCSelfTestResult; ///< RTC self-test status variable. static RTC_RAM_STATUS_T RTCRAMStatus; ///< RTC RAM status variable. static RTC_RAM_STATE_T RTCRAMState; ///< RTC RAM state. static RTC_TIMESTAMP_T RTCTimestampStruct; ///< Timestamp record - last read from RTC. static RTC_TIMESTAMP_T RTCNewTimestampStruct; ///< New timestamp record that will hold the new time to be written to RTC. static U32 RTCSelfTestTimer; ///< Self test timer. static U32 RTCPreviousSecond; ///< Previous second for self-test comparison. static U32 RAMBufferLength; ///< RAM buffer length for RAM operations. static U32 lastEpochTime; ///< Last epoch time. static U32 previousTransferLength; ///< Previous transfer length. static U32 timeCounter; ///< Initial time counter (1). static U32 numberOfFailedRTCTransfers; ///< Initial number of failed RTC transactions (1). static BOOL hasWriteToRTCRequested; ///< Flag to request RTC write. static BOOL hasWriteToRAMRequested; ///< Flag to write to RTC RAM. static BOOL hasReadFromRAMRequested; ///< Flag to read from RTC RAM. static BOOL isRTCServiceOnEntry; ///< Flag to check if service is on entry. static BOOL isTimestampBufferReady; ///< Flag to check if the timestamp buffer is ready. static U16 rxBuffer[ MIBSPI_MAX_BUFFER_LENGTH + 1 ]; ///< Buffer to receive data from RTC. static U16 txBuffer[ MIBSPI_MAX_BUFFER_LENGTH + 1 ]; ///< Buffer to transmit data to RTC. 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. // DEN-15979 testing static U08 debugEventBuffer[DEBUG_EVENT_FIXED_BUFFER_SIZE]; ///< debug event buffer static U16 writeSaveBuffer[ MIBSPI_MAX_BUFFER_LENGTH + 1 ]; ///< Buffer to store data written to RTC. #ifdef _DG_ static BOOL syncDG2HDDateTimeFlag; ///< Flag indicating whether DG RTC should be sync'd to HD RTC. #endif /// 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 }; // ********** Private function prototypes ********* static BOOL serviceRTC( U16* bufferTransmit, U16* bufferReceive, U16 bufferLength ); static BOOL isRTCFunctional( void ); static U08 convertBCD2Decimal( U08 bcd ); static U08 convertDecimal2BCD( U08 decimal ); static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ); static BOOL convertEpoch2DateTime( U32 epoch ); 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 ); static RTC_SELF_TEST_STATE_T handleSelfTestWaitForFirstSecond( void ); static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy( void ); static RTC_SELF_TEST_STATE_T handleSelfTestCheckRTCYear( void ); static RTC_EXEC_STATE_T handleExecIdleState( void ); static RTC_EXEC_STATE_T handleExecReadState( void ); static RTC_EXEC_STATE_T handleExecPrepRAMState( void ); static RTC_EXEC_STATE_T handleExecWriteToRAMState( void ); static RTC_EXEC_STATE_T handleExecReadFromRAMState( void ); static RTC_EXEC_STATE_T handleExecWriteState( void ); static RTC_EXEC_STATE_T handleExecVerifyWriteState( void ); /*********************************************************************//** * @brief * The initRTC initializes the RTC module. * @details Inputs: none * @details Outputs: RTCSelfTestState, RTCSelfTestState * @return none *************************************************************************/ void initRTC( void ) { RTCSelfTestState = RTC_SELF_TEST_STATE_START; RTCServiceState = RTC_SEND_COMMAND; RTCExecState = RTC_EXEC_STATE_IDLE; RTCSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; RTCRAMStatus = RTC_RAM_STATUS_IDLE; RTCRAMState = RTC_RAM_STATE_READY; RTCSelfTestTimer = 0; RTCPreviousSecond = 0; RAMBufferLength = 0; lastEpochTime = 0; previousTransferLength = 0; timeCounter = 1; numberOfFailedRTCTransfers = 1; hasWriteToRTCRequested = FALSE; hasWriteToRAMRequested = FALSE; hasReadFromRAMRequested = FALSE; isRTCServiceOnEntry = FALSE; isTimestampBufferReady = FALSE; previousFPGATimerCount = 0; #ifdef _DG_ syncDG2HDDateTimeFlag = FALSE; #endif #ifdef _DG_ initPersistentAlarm( ALARM_ID_DG_RTC_CONFIG_ERROR, RTC_REG_ERROR_TIMEOUT_MS, RTC_REG_ERROR_TIMEOUT_MS ); #endif #ifdef _HD_ initPersistentAlarm( ALARM_ID_HD_RTC_CONFIG_ERROR, RTC_REG_ERROR_TIMEOUT_MS, RTC_REG_ERROR_TIMEOUT_MS ); #endif } /*********************************************************************//** * @brief * The setRTCTimestamp gets the timestamp values from caller, converts them * into BCD format and inserts them into the txBuffer to be written into the RTC. * @details Inputs: RTCNewTimestampStruct, hasWriteToRTCRequested, isTimestampBufferReady * @details Outputs: RTCNewTimestampStruct, hasWriteToRTCRequested, isTimestampBufferReady * @param secs seconds * @param mins minutes * @param hours hours * @param days days * @param months months * @param years years * @return TRUE is the provided data is valid *************************************************************************/ BOOL setRTCTimestamp( U08 secs, U08 mins, U08 hours, U08 days, U08 months, U32 years ) { BOOL isDataOk = TRUE; if ( secs > MAX_ALLOWED_SECONDS ) { isDataOk = FALSE; } else if ( mins > MAX_ALLOWED_MINUTES ) { isDataOk = FALSE; } else if ( hours > MAX_ALLWOED_HOURS ) { isDataOk = FALSE; } else if ( days < MIN_ALLOWED_DAYS || days > MAX_ALLOWED_DAYS ) { isDataOk = FALSE; } else if ( months < MIN_ALLOWED_MONTHS || months > MAX_ALLOWED_MONTHS ) { isDataOk = FALSE; } else if ( ( years - YEAR_2000 ) > MAX_ALLOWED_YEARS ) { isDataOk = FALSE; } else { hasWriteToRTCRequested = TRUE; isTimestampBufferReady = FALSE; RTCNewTimestampStruct.seconds = secs; RTCNewTimestampStruct.minutes = mins; RTCNewTimestampStruct.hours = hours; RTCNewTimestampStruct.days = days; RTCNewTimestampStruct.weekdays = 0; // Weekdays will not be used RTCNewTimestampStruct.months = months; RTCNewTimestampStruct.years = years; } return isDataOk; } /*********************************************************************//** * @brief * The setRTCEpoch sets the clock from a given epoch. * @details Inputs: none * @details Outputs: none * @param epoch date/time stamp epoch * @return TRUE if valid epoch time received, FALSE if not. * @note If the epoch time is valid, the RTCNewTimeStampStruct updated *************************************************************************/ BOOL setRTCEpoch( U32 epoch ) { BOOL result; result = convertEpoch2DateTime( epoch ); return result; } /*********************************************************************//** * @brief * The execRTCSelfTest runs the RTC POST during the self-test. * @details Inputs: RTCSelfTestState * @details Outputs: RTCSelfTestState, alarm if invalid state was called * @return RTCSelfTestResult the result of self-test *************************************************************************/ SELF_TEST_STATUS_T execRTCSelfTest( void ) { switch ( RTCSelfTestState ) { case RTC_SELF_TEST_STATE_START: RTCSelfTestState = handleSelfTestStart(); break; case RTC_SELF_TEST_STATE_CHECK_CTRL_REGS: RTCSelfTestState = handleSelfTestCheckCtrlRegs(); break; case RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND: RTCSelfTestState = handleSelfTestWaitForFirstSecond(); break; case RTC_SELF_TEST_STATE_CHECK_ACCURACY: RTCSelfTestState = handleSelfTestCheckAccuracy(); break; case RTC_SELF_TEST_STATE_CHECK_RTC_YEAR: RTCSelfTestState = handleSelfTestCheckRTCYear(); break; case RTC_SELF_TEST_STATE_COMPLETE: // Done with POST regardless of the results break; default: #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, RTCSelfTestState ); #else SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, RTCSelfTestState ); #endif RTCSelfTestResult = SELF_TEST_STATUS_FAILED; RTCSelfTestState = RTC_SELF_TEST_STATE_COMPLETE; break; } return RTCSelfTestResult; } /*********************************************************************//** * @brief * The execRTC function executes a signle pass of the RTC monitor state machine. * @details Inputs: RTCExecState * @details Outputs: RTCExecState, alarm if invalid state was called * @return none *************************************************************************/ void execRTC( void ) { switch ( RTCExecState ) { case RTC_EXEC_STATE_IDLE: RTCExecState = handleExecIdleState(); break; case RTC_EXEC_STATE_PREP_RAM: RTCExecState = handleExecPrepRAMState(); break; case RTC_EXEC_STATE_WRITE_TO_RAM: RTCExecState = handleExecWriteToRAMState(); break; case RTC_EXEC_STATE_READ_FROM_RAM: RTCExecState = handleExecReadFromRAMState(); break; case RTC_EXEC_STATE_WRITE: RTCExecState = handleExecWriteState(); break; case RTC_EXEC_STATE_VERIFY_WRITE: RTCExecState = handleExecVerifyWriteState(); break; case RTC_EXEC_STATE_READ: RTCExecState = handleExecReadState(); break; default: #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RTC_EXEC_INVALID_STATE, RTCExecState ); #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_RTC_EXEC_INVALID_STATE, RTCExecState ); #endif RTCExecState = RTC_EXEC_STATE_IDLE; break; } } /*********************************************************************//** * @brief * The getRTCTimestamp returns the current time in epoch format. * @details Inputs: lastEpochTime * @details Outputs: none * @return lastEpochTime the time in epoch as a U32 *************************************************************************/ U32 getRTCTimestamp( void ) { 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 * The signalSyncToHD signals this module to sync RTC with date/time from * HD RTC. * @details Inputs: none * @details Outputs: syncDG2HDDateTimeFlag * @return lastEpochTime the time in epoch as a U32 *************************************************************************/ void signalSyncToHD( void ) { syncDG2HDDateTimeFlag = TRUE; } /*********************************************************************//** * @brief * The syncDG2HDDateTime determines whether it is time to sync date/time * with HD RTC. * @details Inputs: syncDG2HDDateTimeFlag * @details Outputs: syncDG2HDDateTimeFlag * @return TRUE if time to sync DG to HD date time, FALSE if not *************************************************************************/ BOOL syncDG2HDDateTime( void ) { BOOL result = syncDG2HDDateTimeFlag; syncDG2HDDateTimeFlag = FALSE; return result; } #endif /*********************************************************************//** * @brief * The writeToRAM checks whether the RAM status is idle and if it is, it * will check input address and length to make sure they are within the * range. If everything is fine, it will prepare the txBuffer and set the * RAM status to busy. * @details Inputs: RTCRAMStatus, RTCRAMState, hasWriteToRAMRequested, RAMBufferLength, * prepRAMBuffer, txBuffer * @details Outputs: RTCRAMStatus, RTCRAMState, hasWriteToRAMRequested, RAMBufferLength, * prepRAMBuffer, txBuffer * @param address address of the RTC RAM to write to * @param data address of the data buffer to be written to RAM * @param length length of the buffer * @return status of the RTC RAM *************************************************************************/ RTC_RAM_STATUS_T writeToRAM( U32 address, U08* data, U32 length ) { RTC_RAM_STATUS_T status = RTCRAMStatus; U16 maskedAddress = (U16)( address & MASK_OFF_MSW ); U16 castedHighAddress = maskedAddress / BITS_8_FULL_SCALE; U16 castedLowAddress = maskedAddress % BITS_8_FULL_SCALE; if ( status == RTC_RAM_STATUS_IDLE ) { if ( maskedAddress > MAX_ALLOWED_RTC_RAM_ADDRESS ) { status = RTC_RAM_STATUS_ILLEGAL_ADDRESS; } else if ( length > MAX_ALLOWED_RTC_RAM_BYTES ) { status = RTC_RAM_STATUS_BYTES_EXCEEDED; } else { U08 i; RTCRAMStatus = RTC_RAM_STATUS_IN_PROGRESS; status = RTC_RAM_STATUS_IN_PROGRESS; RTCRAMState = RTC_RAM_STATE_BUSY; hasWriteToRAMRequested = TRUE; RAMBufferLength = length; prepRAMBuffer [ RTC_PREP_RAM_INDEX ] = RTC_PREP_RAM_READ_WRITE; prepRAMBuffer [ RTC_RAM_HIGH_ADDRESS_INDEX ] = castedHighAddress; prepRAMBuffer [ RTC_RAM_LOW_ADDRESS_INDEX ] = castedLowAddress; txBuffer [ BUFFER_INDEX_0 ] = RTC_WRITE_TO_RAM; for ( i = 0; i < RAMBufferLength; i++ ) { txBuffer [ i + BUFFER_INDEX_1 ] = data [ i ]; } } } return status; } /*********************************************************************//** * @brief * The readFromRAM checks whether the RAM status is idle and if it is, it * will check input address and length to make sure they are within the * range. If everything is fine, it will prepare the txBuffer and set the * RAM status to busy. * @details Inputs: RTCRAMStatus, RTCRAMState, hasReadFromRAMRequested, RAMBufferLength, * prepRAMBuffer, txBuffer * @details Outputs: RTCRAMStatus, RTCRAMState, hasReadFromRAMRequested, RAMBufferLength, * prepRAMBuffer, txBuffer * @param address address of the RTC RAM to read data from * @param length length of data to be read from RAM * @return status of the RTC RAM *************************************************************************/ RTC_RAM_STATUS_T readFromRAM( U32 address, U32 length ) { RTC_RAM_STATUS_T status = RTCRAMStatus; U16 maskedAddress = (U16)( address & MASK_OFF_MSW ); U16 castedHighAddress = maskedAddress / BITS_8_FULL_SCALE; U16 castedLowAddress = maskedAddress % BITS_8_FULL_SCALE; if ( status == RTC_RAM_STATUS_IDLE ) { if ( maskedAddress > MAX_ALLOWED_RTC_RAM_ADDRESS ) { status = RTC_RAM_STATUS_ILLEGAL_ADDRESS; } else if ( length > MAX_ALLOWED_RTC_RAM_BYTES ) { status = RTC_RAM_STATUS_BYTES_EXCEEDED; } else { U08 i; status = RTC_RAM_STATUS_IN_PROGRESS; RTCRAMStatus = RTC_RAM_STATUS_IN_PROGRESS; RTCRAMState = RTC_RAM_STATE_BUSY; hasReadFromRAMRequested = TRUE; RAMBufferLength = length; prepRAMBuffer[ RTC_PREP_RAM_INDEX ] = RTC_PREP_RAM_READ_WRITE; prepRAMBuffer[ RTC_RAM_HIGH_ADDRESS_INDEX ] = castedHighAddress; prepRAMBuffer[ RTC_RAM_LOW_ADDRESS_INDEX ] = castedLowAddress; txBuffer[ BUFFER_INDEX_0 ] = RTC_READ_FROM_RAM; for ( i = 0; i < RAMBufferLength; i++ ) { txBuffer[ i + BUFFER_INDEX_1 ] = 0x0000; } } } return status; } /*********************************************************************//** * @brief * The getRTCRAMState returns the RAM state. * @details Inputs: RTCRAMState * @details Outputs: none * @return RTC RAM state *************************************************************************/ RTC_RAM_STATE_T getRTCRAMState( void ) { return RTCRAMState; } /*********************************************************************//** * @brief * The getRTCRAMStatus returns the RAM status. If the RAM status is complete * it will set the RAM status to Idle and the RAM state to Ready. * @details Inputs: RTCRAMStatus, RTCRAMState * @details Outputs: RTCRAMStatus, RTCRAMState * @return RTC RAM status *************************************************************************/ RTC_RAM_STATUS_T getRTCRAMStatus( void ) { if ( RTCRAMStatus == RTC_RAM_STATUS_COMPLETE ) { RTCRAMStatus = RTC_RAM_STATUS_IDLE; RTCRAMState = RTC_RAM_STATE_READY; } return RTCRAMStatus; } /*********************************************************************//** * @brief * The getDataFromRAM populates the provided external buffer with the data * in the specified address in the RTC RAM. * @details Inputs: RAMBuffer * @details Outputs: none * @param externalBuffer address of the external buffer to copy data into * @param length length of data to be copied into buffer * @return none *************************************************************************/ void getDataFromRAM( U08* externalBuffer, U32 length ) { U08 i; for ( i = 0; i < length; i++ ) { externalBuffer[ i ] = RAMBuffer[ i + 1 ] & MASK_OFF_MSB; } } //TODO fill up the functions /*void mibspiNotification(mibspiBASE_t *mibspi, uint32 flags) { } void mibspiGroupNotification(mibspiBASE_t *mibspi, uint32 group) { } */ /*********************************************************************//** * @brief * The serviceRTC is the interface to the RTC chip: * If it was called for the first time, it will send the command * If the provided buffer length is not the same as previous, it will * set the buffer length. Otherwise it will ignore it * If it was not called for the first time, it will wait to the buffer * to be transmitted and then it will populate the provided receive buffer * If the transaction failed, it will try 3 time before it fails. * @details Inputs: isRTCServiceOnEntry, RTCServiceState, numberOfFailedRTCTransfers, * previousTransferLength * @details Outputs: isRTCServiceOnEntry, RTCServiceState, numberOfFailedRTCTransfers, * previousTransferLength * @return TRUE if RTC operation was successful *************************************************************************/ static BOOL serviceRTC( U16* bufferTransmit, U16* bufferReceive, U16 bufferLength ) { BOOL result = FALSE; BOOL isBufferOk = FALSE; if ( isRTCServiceOnEntry ) { RTCServiceState = RTC_SEND_COMMAND; } switch ( RTCServiceState ) { case RTC_SEND_COMMAND: if ( previousTransferLength == bufferLength ) { isBufferOk = TRUE; } else if ( setMibSPIBufferLength( bufferLength ) ) { isBufferOk = TRUE; } if ( isBufferOk ) { mibspiSetData( mibspiREG3, MIBSPI_GROUP_ZERO, bufferTransmit ); mibspiTransfer( mibspiREG3, MIBSPI_GROUP_ZERO ); numberOfFailedRTCTransfers = 0; previousTransferLength = bufferLength; RTCServiceState = RTC_WAIT_FOR_TRANSFER_AND_READ; } else { RTCServiceState = RTC_SERVICE_COMPLETE; } isRTCServiceOnEntry = FALSE; break; case RTC_WAIT_FOR_TRANSFER_AND_READ: if ( mibspiIsTransferComplete( mibspiREG3, MIBSPI_GROUP_ZERO ) ) { mibspiGetData( mibspiREG3, MIBSPI_GROUP_ZERO, bufferReceive ); RTCServiceState = RTC_SERVICE_COMPLETE; result = TRUE; } else if ( numberOfFailedRTCTransfers >= MAX_ALLOWED_FAILED_RTC_TRANSFERS ) { RTCServiceState = RTC_SERVICE_COMPLETE; } else { // Transfer to RTC failed. This transfer should be done in 50ms numberOfFailedRTCTransfers++; memset( debugEventBuffer, 0x00, sizeof(debugEventBuffer) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC SPI: %d, %d", RTCServiceState, numberOfFailedRTCTransfers ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); } // Done with read (successful of failed) // get ready for another call isRTCServiceOnEntry = TRUE; break; case RTC_SERVICE_COMPLETE: // Done with reading and transfer break; default: // We should never get here break; } return result; } /*********************************************************************//** * @brief * The isRTCFunctional checks whether the RTC is still functional by checking * the bits in the first 3 control registers. The function ignore the clear * flags. * @details Inputs: rxBuffer * @details Outputs: alarm if any of the control registers are at fault * @return TRUE if the control registers are normal *************************************************************************/ static BOOL isRTCFunctional( void ) { 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_ reg1Alarm = ALARM_ID_DG_RTC_CONFIG_ERROR; batteryAlarm = ALARM_ID_DG_RTC_BATTERY_LOW; #endif #ifdef _HD_ reg1Alarm = ALARM_ID_HD_RTC_CONFIG_ERROR; batteryAlarm = ALARM_ID_HD_RTC_BATTERY_LOW; #endif controlReg1 = controlReg1 & MASK_OFF_MSB; controlReg2 = controlReg2 & MASK_OFF_MSB; controlReg3 = controlReg3 & MASK_OFF_MSB; // Ignore the clear flags controlReg2 = controlReg2 & ~RTC_REG_2_MSF_MASK; controlReg2 = controlReg2 & ~RTC_REG_2_CDTF_MASK; controlReg2 = controlReg2 & ~RTC_REG_2_AF_MASK; controlReg2 = controlReg2 & ~RTC_REG_2_TSF2_MASK; controlReg3 = controlReg3 & ~RTC_REG_3_BF_MASK; if ( controlReg1 & RTC_REG_1_12_HOUR_MODE_MASK ) { hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_PORO ) { hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_CLK_STOPPED_MASK ) { hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_UNUSED_MASK ) { hasReg1Failed = TRUE; } if ( controlReg1 & RTC_REG_1_EXT_CLK_MODE_MASK ) { hasReg1Failed = TRUE; } if ( controlReg3 & RTC_REG_3_BLF_MASK ) { isBatteryLow = TRUE; } status = ( ( FALSE == hasReg1Failed ) && ( FALSE == isBatteryLow ) ? TRUE : FALSE ); checkPersistentAlarm( reg1Alarm, hasReg1Failed, controlReg1, 0 ); checkPersistentAlarm( batteryAlarm, isBatteryLow, controlReg3, 0 ); return status; } /*********************************************************************//** * @brief * The convertBCD2Decimal converts the BCD values to decimal. * @details Inputs: none * @details Outputs: none * @param bcd the number in bcd * @return number is decimal a U08 *************************************************************************/ static U08 convertBCD2Decimal( U08 bcd ) { U08 bcdHigh; U08 bcdLow; U08 decimal; bcdHigh = ( bcd & MASK_OFF_NIBBLE_LSB ) >> SHIFT_BITS_BY_4; bcdLow = ( bcd & MASK_OFF_NIBBLE_MSB ); if ( ( bcdHigh > MAX_SINGLE_DIGIT_DECIMAL ) || ( bcdLow > MAX_SINGLE_DIGIT_DECIMAL ) ) { decimal = 0; } else { decimal = ( bcdHigh * TEN ) + bcdLow; } return decimal; } /*********************************************************************//** * @brief * The convertDecimal2BCD converts the decimal values to BCD. * @details Inputs: none * @details Outputs: none * @param decimal number if decimal * @return number in bcd as a U08 *************************************************************************/ static U08 convertDecimal2BCD( U08 decimal ) { U08 decimalHigh; U08 decimalLow; U08 bcd; if ( decimal > MAX_DOUBLE_DIGIT_DECIMAL ) { bcd = 0; } else { decimalHigh = decimal / TEN; decimalLow = decimal % TEN; bcd = ( decimalHigh << SHIFT_BITS_BY_4 ) + decimalLow; } return bcd; } /*********************************************************************//** * @brief * The convertTime2Epoch converts a given date/time record into an epoch * (seconds from Jan 1 1970). * @details Inputs: none * @details Outputs: none * @param dateTime UTC Date & Time structure to convert to epoch * @return epoch time (seconds since Jan 1, 1970) *************************************************************************/ static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ) { U32 epoch; U32 i, dayCnt; U32 secs = dateTime.seconds; // Expecting seconds to be 0..59. U32 mins = dateTime.minutes; // Expecting minutes to be 0..59. U32 hrs = dateTime.hours; // Expecting hours to be 0..23. U32 days = dateTime.days - 1; // Expecting days to be 1..31. Current (partial) day covered by hrs, min, sec so subtract current day. U32 yrs = dateTime.years + YEAR_2000 - EPOCH_BASE_YEAR; // Expecting 2-digit year - no century from our RTC - so must assume year is >= 2000 - then subtract epoch base year. U32 lyrs = ( yrs / 4 ) + ( yrs % 4 > 2 ? 1 : 0 ); // First leap year after epoch base year (1970) is 1972 (so every 3rd of every 4 years). BOOL leap = ( dateTime.years % 4 == 0 ? TRUE : FALSE ); // Compute number of full days since start of given year. daysInMonth[ LEAP_YEAR_MONTH ] = ( TRUE == leap ? 29 : 28 ); dayCnt = 0; for ( i = 1; i < dateTime.months; i++ ) // Expecting months to be 1..12 { dayCnt += daysInMonth[ i-1 ]; } // Compute epoch from given date/time. epoch = secs + ( mins * SEC_PER_MIN ) + ( hrs * SECS_IN_HOUR ); epoch += ( days * SECONDS_IN_A_DAY ); epoch += ( dayCnt * SECONDS_IN_A_DAY ); epoch += ( lyrs * SECONDS_IN_LEAP_YEAR ); epoch += ( ( yrs - lyrs ) * SECONDS_IN_NORMAL_YEAR ); return epoch; } /*********************************************************************//** * @brief * The convertEpoch2DateTime converts a given epoch to a date/time record (UTC). * @details Inputs: none * @details Outputs: Sets the RTC to the date/time converted from given epoch. * @param epoch Number of seconds since Jan 1, 1970 * @return TRUE if conversion successful, FALSE if not *************************************************************************/ static BOOL convertEpoch2DateTime( U32 epoch ) { BOOL result; RTC_TIMESTAMP_T dtTime; U32 i, dayCnt; U32 fourYears = epoch / SECONDS_IN_4_YEARS; U32 twoYrEpoch = epoch - ( fourYears * SECONDS_IN_4_YEARS ); U32 twoYears = twoYrEpoch / SECONDS_IN_2_YEARS; U32 oneYrEpoch = twoYrEpoch - ( twoYears * SECONDS_IN_2_YEARS ); U32 oneYears = ( twoYears > 0 ? oneYrEpoch / SECONDS_IN_LEAP_YEAR : oneYrEpoch / SECONDS_IN_NORMAL_YEAR ); U32 days34 = ( oneYears > 0 ? ( oneYrEpoch - SECONDS_IN_LEAP_YEAR ) / SECONDS_IN_A_DAY : oneYrEpoch / SECONDS_IN_A_DAY ); U32 days12 = ( oneYears > 0 ? ( oneYrEpoch - SECONDS_IN_NORMAL_YEAR ) / SECONDS_IN_A_DAY : oneYrEpoch / SECONDS_IN_A_DAY ); U32 days = ( twoYears > 0 ? days34 : days12 ); U32 wholeYears = ( fourYears * 4 ) + ( twoYears * 2 ) + oneYears; BOOL leapYear = ( twoYears > 0 && 0 == oneYears ? TRUE : FALSE ); U32 oneDayEpoch = oneYrEpoch % SECONDS_IN_A_DAY; U32 hours = oneDayEpoch / SECS_IN_HOUR; U32 oneHrEpoch = oneDayEpoch - ( hours * SECS_IN_HOUR ); U32 mins = oneHrEpoch / SEC_PER_MIN; U32 secs = oneHrEpoch - ( mins * SEC_PER_MIN ); dtTime.years = EPOCH_BASE_YEAR + wholeYears; dtTime.months = 0; dayCnt = 0; daysInMonth[ LEAP_YEAR_MONTH ] = ( TRUE == leapYear ? 29 : 28 ); for ( i = 0; i < MONTHS_IN_YEAR; i++ ) { if ( days >= dayCnt ) { dtTime.months = i + 1; dtTime.days = days - dayCnt; } dayCnt += daysInMonth[ i ]; } dtTime.days += 1; // days will be number of full days in current month so need to add 1 for the partial current day to get day of month dtTime.hours = hours; dtTime.minutes = mins; dtTime.seconds = secs; result = setRTCTimestamp( dtTime.seconds, dtTime.minutes, dtTime.hours, dtTime.days, dtTime.months, dtTime.years ); return result; } /*********************************************************************//** * @brief * The updateReadTimestampStruct function updates the time structure * after every read. * @details Inputs: RTCTimestampStruct * @details Outputs: RTCTimestampStruct * @return none *************************************************************************/ static void updateReadTimestampStruct( void ) { RTCTimestampStruct.seconds = convertBCD2Decimal( rxBuffer[ RTC_SECONDS_INDEX ] ); RTCTimestampStruct.minutes = convertBCD2Decimal( rxBuffer[ RTC_MINUTES_INDEX ] ); RTCTimestampStruct.hours = convertBCD2Decimal( rxBuffer[ RTC_HOURS_INDEX ] ); RTCTimestampStruct.days = convertBCD2Decimal( rxBuffer[ RTC_DAYS_INDEX ] ); RTCTimestampStruct.weekdays = 0; // Weekdays will not be used RTCTimestampStruct.months = convertBCD2Decimal( rxBuffer[ RTC_MONTHS_INDEX ] ); RTCTimestampStruct.years = convertBCD2Decimal( rxBuffer[ RTC_YEARS_INDEX ] ); } /*********************************************************************//** * @brief * The setMibSPIBufferLength sets the MibSPI buffer length prior to every * RTC transaction. * @details Inputs: none * @details Outputs: none * @param length length of data transfer in bytes * @return TRUE if the buffer length was set successfully *************************************************************************/ static BOOL setMibSPIBufferLength( U16 length ) { BOOL transferStatus = FALSE; // The max allowed buffer length in the // MibSPI RAM is 127 if ( length <= MIBSPI_MAX_BUFFER_LENGTH ) { U32 i = 0; mibspiREG3->TGCTRL[0U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[1U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[1U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[2U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[2U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[3U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[3U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[4U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[4U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[5U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[5U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[6U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[6U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[7U] &= ~(uint32)( (uint32)MIBSPI_MAX_BUFFER_LENGTH << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[7U] |= (uint32)( (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); mibspiREG3->TGCTRL[8U] = (uint32)length << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8; mibspiREG3->LTGPEND = ( mibspiREG3->LTGPEND & 0xFFFF00FFU ) | (uint32)( ((uint32)length - 1U) << MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 ); while ( i < ( length - 1U ) ) { mibspiRAM3->tx[i].control = (uint16)( (uint16)MIBSPI_CONTINUOUS_MODE << MIBSPI_BUFFER_MODE_BIT_SHIFT_13 ) /* buffer mode */ | (uint16)( (uint16)MIBSPI_CHIP_SELECT_ACTIVE << MIBSPI_CHIP_SELECT_BIT_SHIFT_12 ) /* chip select hold */ | (uint16)( (uint16)MIBSPI_NO_WDELAY << MIBSPI_NO_WDELAY_BIT_SHIFT_10 ) /* enable WDELAY */ | (uint16)( (uint16)MIBSPI_LOCK_TG << MIBSPI_LOCK_TRANS_BIT_SHIFT_11 ) /* lock transmission */ | (uint16)( (uint16)MIBSPI_DATA_FORMAT_ZERO << MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT_8 ) /* data format */ | ((uint16)( ~((uint16)0xFFU ^ (uint16)CS_1)) & (uint16)0x00FFU ); /* chip select */ i++; } mibspiRAM3->tx[i].control = (uint16)( (uint16)MIBSPI_CONTINUOUS_MODE << MIBSPI_BUFFER_MODE_BIT_SHIFT_13 ) /* buffer mode */ | (uint16)( (uint16)MIBSPI_CHIP_SELECT_DEACTIVE << MIBSPI_CHIP_SELECT_BIT_SHIFT_12 ) /* chip select hold */ | (uint16)( (uint16)MIBSPI_NO_WDELAY << MIBSPI_NO_WDELAY_BIT_SHIFT_10 ) /* enable WDELAY */ | (uint16)( (uint16)MIBSPI_DATA_FORMAT_ZERO << MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT_8 ) /* data format */ | ((uint16)( ~((uint16)0xFFU ^ (uint16)CS_1)) & (uint16)0x00FFU ); /* chip select */ transferStatus = TRUE; } else { transferStatus = FALSE; } return transferStatus; } /*********************************************************************//** * @brief * The prepBufferForReadCommand sets the txBuffer for a read. * @details Inputs: txBuffer * @details Outputs: txBuffer * @param length length of buffer to read * @return none *************************************************************************/ static void prepBufferForReadCommand( U08 length ) { U08 i; txBuffer[ BUFFER_INDEX_0 ] = RTC_READ_FROM_REG0; for ( i = 1; i < length; i++ ) { txBuffer[ i ] = 0x0000; } } /*********************************************************************//** * @brief * The handleExecIdleState checks whether read or write to RTC or RAM has * been requested. If none of them have been requested, it will increment the * timer. * @details Inputs: nohasWriteToRTCRequested, hasWriteToRAMRequested, * hasReadFromRAMRequested, timeCounter * @details Outputs: timeCounter * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecIdleState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_IDLE; if ( TRUE == hasWriteToRTCRequested ) { result = RTC_EXEC_STATE_WRITE; } else if ( TRUE == hasWriteToRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } else if ( TRUE == hasReadFromRAMRequested ) { result = RTC_EXEC_STATE_PREP_RAM; } else if ( TIMER_COUNTER_TO_REQUEST_READ <= timeCounter ) { if ( TRUE == getSemaphore( SEMAPHORE_RTC ) ) { prepBufferForReadCommand( RTC_GENERAL_BUFFER_LENGTH ); result = RTC_EXEC_STATE_READ; } } else { timeCounter++; } return result; } /*********************************************************************//** * @brief * The handleExecWriteState writes timestamp to RTC. * @details Inputs: isTimestampBufferReady, txBuffer, hasWriteToRTCRequested, * timeCounter, RTCServiceState * @details Outputs: isTimestampBufferReady, txBuffer, hasWriteToRTCRequested, * timeCounter, alarm if any RTC RAM operations occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecWriteState( void ) { if ( FALSE == isTimestampBufferReady ) { txBuffer[ 0 ] = RTC_WRITE_TO_REG0; txBuffer[ 1 ] = 0x0000; 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 ) ); isTimestampBufferReady = TRUE; } RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WRITE; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { memcpy(writeSaveBuffer, txBuffer, ( RTC_GENERAL_BUFFER_LENGTH * 2 ) ); releaseSemaphore( SEMAPHORE_RTC ); // Reset the counter to start with the new read timeCounter = 1; hasWriteToRTCRequested = FALSE; prepBufferForReadCommand(RTC_GENERAL_BUFFER_LENGTH); result = RTC_EXEC_STATE_VERIFY_WRITE; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); #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; } return result; } /*********************************************************************//** * @brief * The handleExecPrepRAMState prepares the RAM for read or write. * @details Inputs: RTCServiceState, hasWriteToRAMRequested, hasReadFromRAMRequested, * prepRAMBuffer, RAMBuffer * @details Outputs: alarm if any RTC RAM operations error occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecPrepRAMState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_PREP_RAM; BOOL isStatusOk = serviceRTC( prepRAMBuffer, RAMBuffer, RTC_RAM_PREP_BUFFER_LENGTH ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { if ( hasWriteToRAMRequested ) { result = RTC_EXEC_STATE_WRITE_TO_RAM; } else if ( hasReadFromRAMRequested ) { result = RTC_EXEC_STATE_READ_FROM_RAM; } } else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); #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; } return result; } /*********************************************************************//** * @brief * The handleExecWriteToRAMState writes to RAM. * @details Inputs: RTCServiceState, hasWriteToRAMRequested, RTCRAMStatus, txBuffer, * RAMBuffer, RAMBufferLength * @details Outputs: hasWriteToRAMRequested, RTCRAMStatus, alarm if any RTC RAM * operations errors occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecWriteToRAMState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WRITE_TO_RAM; BOOL isStatusOk = serviceRTC( txBuffer, RAMBuffer, RAMBufferLength + 1 ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { releaseSemaphore( SEMAPHORE_RTC ); result = RTC_EXEC_STATE_IDLE; RTCRAMStatus = RTC_RAM_STATUS_COMPLETE; hasWriteToRAMRequested = FALSE; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); RTCRAMStatus = RTC_RAM_STATUS_FAILED; #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; } return result; } /*********************************************************************//** * @brief * The handleExecReadFromRAMState read from RAM. * @details Inputs: RTCServiceState, hasReadFromRAMRequested, RTCRAMStatus, txBuffer, * RAMBuffer, RAMBufferLength * @details Outputs: hasReadFromRAMRequested, RTCRAMStatus, alarm if any RTC RAM * operations errors occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecReadFromRAMState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_READ_FROM_RAM; BOOL isStatusOk = serviceRTC( txBuffer, RAMBuffer, RAMBufferLength + 1 ); if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) { releaseSemaphore( SEMAPHORE_RTC ); result = RTC_EXEC_STATE_IDLE; RTCRAMStatus = RTC_RAM_STATUS_COMPLETE; hasReadFromRAMRequested = FALSE; } else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) { releaseSemaphore( SEMAPHORE_RTC ); RTCRAMStatus = RTC_RAM_STATUS_FAILED; #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; } return result; } /*********************************************************************//** * @brief * The handleExecReadState reads timestamp from RTC. The function calls * other functions to update the time structure and convert the latest time * to epoch. * @details Inputs: RTCServiceState, lastEpochTime, timeCounter, txBuffer, rxBuffer * @details Outputs: lastEpochTime, timeCounter, alarm if any RTC operations error * occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecReadState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_READ; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { if ( TRUE == isRTCFunctional() ) { RTC_DATA_T data; updateReadTimestampStruct(); lastEpochTime = convertDateTime2Epoch( RTCTimestampStruct ); timeCounter = 1; data.epochTime = lastEpochTime; broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, (U08*)&data, sizeof( RTC_DATA_T ) ); } releaseSemaphore( SEMAPHORE_RTC ); result = RTC_EXEC_STATE_IDLE; } else if ( RTC_SERVICE_COMPLETE == RTCServiceState ) { releaseSemaphore( SEMAPHORE_RTC ); #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; } return result; } /*********************************************************************//** * @brief * The handleExecVerifyWriteState reads timestamp from RT to verify the * RTC write was successful. * @details Inputs: RTCServiceState, lastEpochTime, timeCounter, txBuffer, rxBuffer * @details Outputs: lastEpochTime, timeCounter, alarm if any RTC operations error * occurred * @return next state *************************************************************************/ static RTC_EXEC_STATE_T handleExecVerifyWriteState( void ) { RTC_EXEC_STATE_T result = RTC_EXEC_STATE_VERIFY_WRITE; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { // Compare received buffer with what was transmitted if ( 0 != memcmp( &writeSaveBuffer[1], &rxBuffer[1], ( RTC_GENERAL_BUFFER_LENGTH - 1 )* 2 ) ) { memset( debugEventBuffer, 0x00, sizeof( debugEventBuffer ) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC Verify: %02X:%02X, %02X:%02X, %02X:%02X, %02X:%02X", rxBuffer[0], writeSaveBuffer[0], rxBuffer[1], writeSaveBuffer[1], rxBuffer[2], writeSaveBuffer[2], rxBuffer[3], writeSaveBuffer[3] ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); memset( debugEventBuffer, 0x00, sizeof( debugEventBuffer ) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC Verify: %02X:%02X, %02X:%02X, %02X:%02X, %02X:%02X", rxBuffer[4], writeSaveBuffer[4], rxBuffer[5], writeSaveBuffer[5], rxBuffer[6], writeSaveBuffer[6], rxBuffer[7], writeSaveBuffer[7] ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); memset( debugEventBuffer, 0x00, sizeof( debugEventBuffer ) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC Verify: %02X:%02X, %02X:%02X, %02X:%02X", rxBuffer[8], writeSaveBuffer[8], rxBuffer[9], writeSaveBuffer[9], rxBuffer[10], writeSaveBuffer[10] ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); } releaseSemaphore( SEMAPHORE_RTC ); result = RTC_EXEC_STATE_IDLE; } else if ( RTC_SERVICE_COMPLETE == RTCServiceState ) { releaseSemaphore( SEMAPHORE_RTC ); #ifdef _DG_ 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; } return result; } /*********************************************************************//** * @brief * The handleSelfTestStart calls another function to prepare the txBuffer * for a read and sets the state to control registers. * @details Inputs: RTCSelfTestResult * @details Outputs: RTCSelfTestResult * @return next state *************************************************************************/ static RTC_SELF_TEST_STATE_T handleSelfTestStart( void ) { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_START; RTCSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; if ( TRUE == getSemaphore( SEMAPHORE_RTC ) ) { prepBufferForReadCommand( RTC_GENERAL_BUFFER_LENGTH ); result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; } return result; } /*********************************************************************//** * @brief * The handleSelfTestCheckCtrlRegs receives the control registers and calls * another function to check whether RTC is function or not. If the RTC is * functional, it will update the RTCPreviousSecond variable and sets the * state machine to the next state. * @details Inputs: RTCServiceState, txBuffer, rxBuffer, RTCPreviousSecond, * RTCSelfTestResult * @details Outputs: RTCPreviousSecond, RTCSelfTestResult * @return next state *************************************************************************/ static RTC_SELF_TEST_STATE_T handleSelfTestCheckCtrlRegs( void ) { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { if ( TRUE == isRTCFunctional() ) { U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; RTCPreviousSecond = RTCCurrentSecond; result = RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND; } else { releaseSemaphore( SEMAPHORE_RTC ); RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; } } else if ( RTC_SERVICE_COMPLETE == RTCServiceState ) { releaseSemaphore( SEMAPHORE_RTC ); RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; } return result; } /*********************************************************************//** * @brief * The handleSelfTestWaitForFirstSecond continuously reads the RTC and compares * latest second from RTC to the previous second and if it has changed, it will * start the timer and set the state machine to the next state. * @details Inputs: RTCServiceState, txBuffer, rxBuffer, RTCCurrentSecond, RTCSelfTestTimer, * RTCPreviousSecond * @details Outputs: RTCCurrentSecond, RTCSelfTestTimer, RTCPreviousSecond * @return next state *************************************************************************/ static RTC_SELF_TEST_STATE_T handleSelfTestWaitForFirstSecond( void ) { RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND; BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_GENERAL_BUFFER_LENGTH ); if ( ( RTC_SERVICE_COMPLETE == RTCServiceState ) && ( TRUE == isStatusOk ) ) { if ( TRUE == isRTCFunctional() ) { U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; if ( RTCCurrentSecond != RTCPreviousSecond ) { RTCPreviousSecond = RTCCurrentSecond; previousFPGATimerCount = getFPGATimerCount(); RTCSelfTestTimer = getMSTimerCount(); result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; } } else { releaseSemaphore( SEMAPHORE_RTC ); RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; } } else if ( RTC_SERVICE_COMPLETE == RTCServiceState ) { releaseSemaphore( SEMAPHORE_RTC ); RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; } return result; } /*********************************************************************//** * @brief * The handleSelfTestCheckAccuracy checks whether the time has been elapsed * within the specified time tolerance. It will call another function to check * whether one second has elapsed. If the time has elapsed, how much time has * passed since the last second that was read from RTC. * @details Inputs: RTCSelfTestTimer, RTCSelfTestResult * Outputs : RTCSelfTestTimer, RTCSelfTestResult, alarm if RTC time accuracy * test failed * @return Next state *************************************************************************/ 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 ( ( TRUE == isStatusOk ) && ( rxBuffer[ RTC_SECONDS_INDEX ] != RTCPreviousSecond ) ) { updateReadTimestampStruct(); ALARM_ID_T alarm; S32 elapsedTime = (S32)calcTimeSince( RTCSelfTestTimer ); S32 elapsedFPGATime = (S32)u16DiffWithWrap( previousFPGATimerCount, getFPGATimerCount() ); result = RTC_SELF_TEST_STATE_CHECK_RTC_YEAR; #ifdef _DG_ alarm = ALARM_ID_DG_RTC_OR_TIMER_ACCURACY_FAILURE; #endif #ifdef _HD_ alarm = ALARM_ID_HD_RTC_OR_TIMER_ACCURACY_FAILURE; #endif if ( abs( elapsedFPGATime - elapsedTime ) > FPGA_ACCURACY_TOLERANCE ) { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; result = RTC_SELF_TEST_STATE_COMPLETE; SET_ALARM_WITH_2_U32_DATA( alarm, (U32)elapsedFPGATime, (U32)elapsedTime ); } releaseSemaphore( SEMAPHORE_RTC ); } return result; } /*********************************************************************//** * @brief * The handleSelfTestCheckRTCYear checks whether the year that has been set * in RTC is greater than 2021 or not. * @details Inputs: RTCSelfTestTimer * @details Outputs: RTCSelfTestResult * @return next state *************************************************************************/ static RTC_SELF_TEST_STATE_T handleSelfTestCheckRTCYear( void ) { RTC_SELF_TEST_STATE_T state = RTC_SELF_TEST_STATE_COMPLETE; ALARM_ID_T alarm; #ifdef _DG_ alarm = ALARM_ID_DG_SET_RTC_YEAR_INVALID; #endif #ifdef _HD_ alarm = ALARM_ID_HD_SET_RTC_YEAR_INVALID; #endif // Check if the year is not 0, meaning that the year has been read // If the year is greater than 2021, set as pass, otherwise fail POST if ( RTCTimestampStruct.years > ( YEAR_2021 - YEAR_2000 ) ) { RTCSelfTestResult = SELF_TEST_STATUS_PASSED; } else { RTCSelfTestResult = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_1_U32_DATA( alarm, (U16)RTCTimestampStruct.years ); } 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 *************************************************************************/ /*********************************************************************//** * @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; } /*********************************************************************//** * @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; } /*********************************************************************//** * @brief * The isEpochValid check if epoch is valid * @details Inputs: epoch time * @details Outputs: None * @return TRUE if epoch is valid, else false *************************************************************************/ BOOL isEpochValid( U32 epoch ) { BOOL result = TRUE; memset( debugEventBuffer, 0x00, sizeof( debugEventBuffer ) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC HD epoch check" ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); if ( epoch < MIN_EPOCH_DATE ) { result = FALSE; memset( debugEventBuffer, 0x00, sizeof( debugEventBuffer ) ); snprintf( debugEventBuffer, sizeof( debugEventBuffer ), "$RTC HD epoch: %d", epoch ); broadcastData( DEBUG_EVENT_MSG_ID, COMM_BUFFER_OUT_CAN_BROADCAST, debugEventBuffer, sizeof( debugEventBuffer ) ); } return result; } /**@}*/