Index: RTC.c =================================================================== diff -u --- RTC.c (revision 0) +++ RTC.c (revision 6e0f785edb79d85bab667147793c4e47d7cabbf0) @@ -0,0 +1,1306 @@ +/************************************************************************** + * + * Copyright (c) 2019-2019 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 + * + * @date 27-Nov-2019 + * @author D. Navaei + * + * @brief Monitor/Controller Real Time Clock + * + **************************************************************************/ +#include // For calculating epoch + +#include "Common.h" +#include "Timers.h" +#include "RTC.h" +#include "mibspi.h" + +// ********** Definitions ********** + +#define RTC_REG_1_12_HOUR_MODE_MASK 0x0004 // 12-hour mode mask +#define RTC_REG_1_PORO 0x0008 // Power On Reset Override +#define RTC_REG_1_CLK_STOPPED_MASK 0x0020 // RTC source clock mask +#define RTC_REG_1_UNUSED_MASK 0x0040 // Unused mask +#define RTC_REG_1_EXT_CLK_MODE_MASK 0x0080 // RTC external clock test mode mask + +#define RTC_REG_2_MSF_MASK 0x0080 // Minute or second interrupt mask +#define RTC_REG_2_CDTF_MASK 0x0008 // Countdown timer interrupt mask +#define RTC_REG_2_AF_MASK 0x0010 // Alarm interrupt mask +#define RTC_REG_2_TSF2_MASK 0x0020 // Timestamp interrupt mask + +#define RTC_REG_3_BF_MASK 0x0008 // Battery status interrupt flag +#define RTC_REG_3_BLF_MASK 0x0004 // Battery status low flag + +// Indices used to check values read from RTC +#define RTC_REG_1_INDEX 1U +#define RTC_REG_2_INDEX 2U +#define RTC_REG_3_INDEX 3U +#define RTC_SECONDS_INDEX 4U +#define RTC_MINUTES_INDEX 5U +#define RTC_HOURS_INDEX 6U +#define RTC_DAYS_INDEX 7U +#define RTC_WEEKDAYS_INDEX 8U +#define RTC_MONTHS_INDEX 9U +#define RTC_YEARS_INDEX 10U + +#define BUFFER_INDEX_0 0U +#define BUFFER_INDEX_1 1U +#define BUFFER_INDEX_2 2U +#define BUFFER_INDEX_3 3U +#define BUFFER_INDEX_4 4U + +#define MIBSPI_MAX_BUFFER_LENGTH 127U +#define MIBSPI_CONTINUOUS_MODE 4U +#define MIBSPI_CHIP_SELECT_ACTIVE 1U +#define MIBSPI_CHIP_SELECT_DEACTIVE 0U +#define MIBSPI_NO_WDELAY 0U +#define MIBSPI_LOCK_TG 0U +#define MIBSPI_DATA_FORMAT_ZERO 0U +#define MIBSPI_GROUP_ZERO 0U + +#define MIBSPI_BUFFER_MODE_BIT_SHIFT_13 13U +#define MIBSPI_CHIP_SELECT_BIT_SHIFT_12 12U +#define MIBSPI_NO_WDELAY_BIT_SHIFT_10 10U +#define MIBSPI_LOCK_TRANS_BIT_SHIFT_11 11U +#define MIBSPI_DATA_FORMAT_ZERO_BIT_SHIFT_8 8U +#define MIBSPI_BUFFER_TRANS_BIT_SHIFT_8 8U + +#define RTC_RAM_PREP_BUFFER_LENGTH 3U +#define RTC_TIMESTAMP_BUFFER_LENGTH 8U +#define RTC_GENERAL_BUFFER_LENGTH 11U + +#define RTC_PREP_RAM_INDEX 0U +#define RTC_RAM_HIGH_ADDRESS_INDEX 1U +#define RTC_RAM_LOW_ADDRESS_INDEX 2U +#define RTC_RAM_COMMAND_INDEX 3U + +#define RTC_READ_FROM_REG0 0x00A0 // RTC read from address 0 +#define RTC_WRITE_TO_REG3 0x0023 // Seconds register +#define RTC_WRITE_TO_REG0 0x0020 +#define RTC_PREP_RAM_READ_WRITE 0x003A // RTC cmd prior to RAM ops +#define RTC_WRITE_TO_RAM 0x003C // RTC RAM write +#define RTC_READ_FROM_RAM 0x00BD // RTC RAM read + +#define RTC_ACCURACY_TIMEOUT 1000U // ms +#define RTC_ACCURACY_TIMEOUT_TOLERANCE 1050U // ms + +#define TIMER_COUNTER_TO_REQUEST_READ 18U +#define MAX_ALLOWED_FAILED_RTC_TRANSFERS 3U +#define MAX_ALLOWED_RTC_RAM_BYTES 100U +#define MAX_ALLOWED_RTC_RAM_ADDRESS 512U +#define TEN 10U +#define YEAR_2000 2000U + +#ifndef _VECTORCAST_ +#define EPOCH_YEAR 1970U +#else +#define EPOCH_YEAR 1900U +#define LOCAL_TO_GTM_TIME_CONVERSION 8U +#endif + +typedef enum RTC_Self_Test_States +{ + RTC_SELF_TEST_STATE_START = 0, + RTC_SELF_TEST_STATE_CHECK_CTRL_REGS, + RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_SECOND, + RTC_SELF_TEST_STATE_WAIT_FOR_SECOND_SECOND, + RTC_SELF_TEST_STATE_CHECK_ACCURACY, + RTC_SELF_TEST_STATE_COMPLETE, + NUM_OF_RTC_SELF_TEST_STATES +} RTC_SELF_TEST_STATE_T; + +typedef enum RTC_Read_Data +{ + RTC_SEND_COMMAND = 0, + RTC_WAIT_FOR_TRANSFER_AND_READ, + RTC_SERVICE_COMPLETE, + NUM_OF_RTC_SERVICE_STATES +} RTC_GET_DATA_STATE_T; + +typedef enum RTC_Exec_State +{ + RTC_EXEC_STATE_WAIT_FOR_POST = 0, + RTC_EXEC_STATE_IDLE, + RTC_EXEC_STATE_PREP_RAM, + RTC_EXEC_STATE_WRITE_TO_RAM, + RTC_EXEC_STATE_READ_FROM_RAM, + RTC_EXEC_STATE_READ, + RTC_EXEC_STATE_WRITE, + RTC_EXEC_STATE_FAULT, + NUM_OF_RTC_EXEC_STATES +} RTC_EXEC_STATE_T; + +#pragma pack(push,4) +typedef struct +{ + U16 seconds; + U16 minutes; + U16 hours; + U16 days; + U16 weekdays; + U16 months; + U16 years; +} RTC_TIMESTAMP_T; +#pragma pack(pop) + +// ********** private data ********** + +static RTC_SELF_TEST_STATE_T RTCSelfTestState = RTC_SELF_TEST_STATE_START; +static RTC_GET_DATA_STATE_T RTCServiceState = RTC_SEND_COMMAND; +static RTC_EXEC_STATE_T RTCExecState = RTC_EXEC_STATE_WAIT_FOR_POST; +static SELF_TEST_STATUS_T RTCSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; +static RTC_RAM_STATUS_T RTCRAMStatus = RTC_RAM_STATUS_IDLE; +static RTC_RAM_STATE_T RTCRAMState = RTC_RAM_STATE_READY; +static RTC_TIMESTAMP_T RTCTimestampStruct; + +static U32 RTCSelfTestTimer = 0; +static U32 RTCPreviousSecond = 0; // Previous second is used to compare seconds in POST +static U32 RAMBufferLength = 0; +static U32 lastEpochTime = 0; // Last value that has been converted to epoch +static U32 previousTransferLength = 0; + +static U32 timeCounter = 1; +static U32 numberOfFailedRTCTransfers = 1; + +static BOOL hasWriteToRTCRequested = FALSE; +static BOOL hasWriteToRAMRequested = FALSE; +static BOOL hasReadFromRAMRequested = FALSE; +static BOOL isRTCServiceOnEntry = FALSE; + +static U16 rxBuffer[ MIBSPI_MAX_BUFFER_LENGTH + 1 ]; +static U16 txBuffer[ MIBSPI_MAX_BUFFER_LENGTH + 1 ]; + +static U16 prepRAMBuffer[ RTC_RAM_PREP_BUFFER_LENGTH ]; +static U16 RAMBuffer[ MIBSPI_MAX_BUFFER_LENGTH ]; + +// ********** 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 convertTime2Epoch( void ); +static void updateReadTimestampStruct( void ); +static BOOL setMibSPIBufferLength( U16 length ); +static void prepBufferForReadCommand( U08 length ); // Puts the read command + +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 ); +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 ); + +// ********** Public functions ********** + +/************************************************************************* + * @brief initRTC + * The initRTC initializes the RTC + * @details + * Inputs : none + * Outputs : The function is empty for now + * @param none + * @return none + *************************************************************************/ + void initRTC( void ) +{ + RTCSelfTestState = RTC_SELF_TEST_STATE_START; + RTCServiceState = RTC_SEND_COMMAND; +} + +/************************************************************************* + * @brief setRTCTimestamp + * The setRTCTimestamp gets the timestamp values, converts them into BCD + * and inserts them into the txBuffer to be written into the RTC + * @details + * Inputs : seconds, minutes, hours, days, months, years + * Outputs : txBuffer will be prepared with the timestamp + * @param none + * @return none + *************************************************************************/ +void setRTCTimestamp( U08 secs, U08 mins, U08 hours, U08 days, U08 months, U16 years ) +{ + hasWriteToRTCRequested = TRUE; + txBuffer[ 0 ] = RTC_WRITE_TO_REG0; + txBuffer[ 1 ] = 0x0000; + txBuffer[ 2 ] = 0x0000; + txBuffer[ 3 ] = 0x0000; + txBuffer[ 4 ] = convertDecimal2BCD( secs ); + txBuffer[ 5 ] = convertDecimal2BCD( mins ); + txBuffer[ 6 ] = convertDecimal2BCD( hours ); + txBuffer[ 7 ] = convertDecimal2BCD( days ); + txBuffer[ 8 ] = convertDecimal2BCD( 0 ); // Weekdays will not be used + txBuffer[ 9 ] = convertDecimal2BCD( months ); + txBuffer[ 10 ] = convertDecimal2BCD( years - YEAR_2000 ); +} + +/************************************************************************* + * @brief execRTCSelfTest + * The execRTCSelfTest runs the RTC POST during the self test + * @details + * Inputs : none + * Outputs : SELF_TEST_STATUS_T + * @param none + * @return SELF_TEST_STATUS_T + *************************************************************************/ +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_WAIT_FOR_SECOND_SECOND: + + RTCSelfTestState = handleSelfTestWaitForSecondSecond(); + break; + + case RTC_SELF_TEST_STATE_CHECK_ACCURACY: + + RTCSelfTestState = handleSelfTestCheckAccuracy(); + break; + + case RTC_SELF_TEST_STATE_COMPLETE: + + // Done with the state + // TODO: If POST failed, set the proper alarm + break; + + default: + + // TODO: Add the alarms + RTCSelfTestResult = SELF_TEST_STATUS_FAILED; + break; + } + + return RTCSelfTestResult; +} + +/************************************************************************* + * @brief execRTC + * The execRTC runs the RTC during normal operations + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void execRTC( void ) +{ + switch ( RTCExecState ) + { + case RTC_EXEC_STATE_WAIT_FOR_POST: + + RTCExecState = handleExecWaitForPostState(); + break; + + 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_READ: + + RTCExecState = handleExecReadState(); + break; + + case RTC_EXEC_STATE_FAULT: + + // Something failed set the alarms + // TODO: set the alarms and stuff + break; + + default: + break; + } +} + +/************************************************************************* + * @brief getRTCTimestamp + * The getRTCTimestamp returns the current time in epoch + * @details + * Inputs : none + * Outputs : current time in epoch + * @param none + * @return lastEpochTime + *************************************************************************/ +U32 getRTCTimestamp( void ) +{ + return lastEpochTime; +} + +/************************************************************************* + * @brief writeToRAM + * 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 : address, data, length + * Outputs : RTC_RAM_STATUS_T + * @param none + * @return RTC_RAM_STATUS_T + *************************************************************************/ +RTC_RAM_STATUS_T writeToRAM( U16 address, U16* data, U32 length ) +{ + RTC_RAM_STATUS_T status = RTCRAMStatus; + + if ( status == RTC_RAM_STATUS_IDLE ) + { + if ( address > 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 = 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 ] = ( address >> SHIFT_8_BITS_FOR_BYTE_SHIFT ); + prepRAMBuffer[ RTC_RAM_LOW_ADDRESS_INDEX ] = ( address & MASK_OFF_MSB ); + txBuffer[ BUFFER_INDEX_0 ] = RTC_WRITE_TO_RAM; + + for ( i = 0; i < RAMBufferLength; i++ ) + { + txBuffer[ i + BUFFER_INDEX_1 ] = data[ i ]; + } + } + } + + return status; +} + +/************************************************************************* + * @brief readFromRAM + * 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 : address, length + * Outputs : RTC_RAM_STATUS_T + * @param none + * @return RTC_RAM_STATUS_T + *************************************************************************/ +RTC_RAM_STATUS_T readFromRAM( U16 address, U32 length ) +{ + RTC_RAM_STATUS_T status = RTCRAMStatus; + + if ( status == RTC_RAM_STATUS_IDLE ) + { + if ( address > 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 = 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 ] = ( address >> SHIFT_8_BITS_FOR_BYTE_SHIFT ); + prepRAMBuffer[ RTC_RAM_LOW_ADDRESS_INDEX ] = ( address & MASK_OFF_MSB ); + txBuffer[ BUFFER_INDEX_0 ] = RTC_READ_FROM_RAM; + + for ( i = 0; i < RAMBufferLength; i++ ) + { + txBuffer[ i + BUFFER_INDEX_1 ] = 0x0000; + } + } + } + + return status; +} + +/************************************************************************* + * @brief getRTCRAMState + * The getRTCRAMState returns the RAM state + * @details + * Inputs : none + * Outputs : RTC_RAM_STATE_T + * @param none + * @return RTC_RAM_STATE_T + *************************************************************************/ +RTC_RAM_STATE_T getRTCRAMState( void ) +{ + return RTCRAMState; +} + +/************************************************************************* + * @brief getRTCRAMStatus + * The getRTCRAMStatus returns the RAM state. If the RAM status is complete + * it will set the RAM status to Idle and the RAM state to Ready + * @details + * Inputs : none + * Outputs : RTC_RAM_STATE_T + * @param none + * @return RTC_RAM_STATE_T + *************************************************************************/ +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 getDataFromRAM + * The getDataFromRAM populates the provided external buffer with the data + * in the specified address in the RAM + * @details + * Inputs : external buffer (pointer), length + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void getDataFromRAM( U16* externalBuffer, U32 length ) +{ + U08 i; + for ( i = 0; i < length; i++ ) + { + externalBuffer[ i ] = RAMBuffer[ i + 1 ]; + } +} + +// ********** Private functions ********* + +/*void mibspiNotification(mibspiBASE_t *mibspi, uint32 flags) +{ + +} + +void mibspiGroupNotification(mibspiBASE_t *mibspi, uint32 group) +{ + +} */ + + +/************************************************************************* + * @brief serviceRTC + * 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 : bufferTransmit, bufferReceive, bufferLength + * Outputs : result (bool) + * @param none + * @return result (bool) + *************************************************************************/ +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++; + } + // 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 isRTCFunctional + * 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 : none + * Outputs : hasTestPassed (bool) + * @param none + * @return hasTestPassed (bool) + *************************************************************************/ +static BOOL isRTCFunctional( void ) +{ + // TODO: Add alarms + BOOL hasTestPassed = TRUE; + 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; + + // 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 ) + { + hasTestPassed = FALSE; + } + if ( controlReg1 & RTC_REG_1_PORO ) + { + hasTestPassed = FALSE; + } + if ( controlReg1 & RTC_REG_1_CLK_STOPPED_MASK ) + { + hasTestPassed = FALSE; + } + if ( controlReg1 & RTC_REG_1_UNUSED_MASK ) + { + hasTestPassed = FALSE; + } + if ( controlReg1 & RTC_REG_1_EXT_CLK_MODE_MASK ) + { + hasTestPassed = FALSE; + } + if ( controlReg3 & RTC_REG_3_BLF_MASK ) + { + hasTestPassed = FALSE; + } + + return hasTestPassed; +} + +/************************************************************************* + * @brief convertBCD2Decimal + * The convertBCD2Decimal converts the BCD values to decimal + * @details + * Inputs : bcd value + * Outputs : decimal value + * @param none + * @return decimal value + *************************************************************************/ +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 ) + { + // ToDo software fault + decimal = 0; + } + else + { + decimal = ( bcdHigh * TEN ) + bcdLow; + } + return decimal; +} + +/************************************************************************* + * @brief convertDecimal2BCD + * The convertDecimal2BCD converts the decimal values to BCD + * @details + * Inputs : decimal value + * Outputs : bcd value + * @param none + * @return bcd value + *************************************************************************/ +static U08 convertDecimal2BCD( U08 decimal ) +{ + U08 decimalHigh; + U08 decimalLow; + U08 bcd; + if ( decimal > MAX_DOUBLE_DIGIT_DECIMAL ) + { + // TODO: Add software fault + bcd = 0; + } + else + { + decimalHigh = decimal / TEN; + decimalLow = decimal % TEN; + bcd = ( decimalHigh << SHIFT_BITS_BY_4 ) + decimalLow; + } + return bcd; +} + +/************************************************************************* + * @brief convertTime2Epoch + * The convertTime2Epoch converts the time into epoch (seconds from Jan 1 1970) + * @details + * Inputs : none + * Outputs : epochTime value + * @param none + * @return epochTime value + *************************************************************************/ +static U32 convertTime2Epoch( void ) +{ + struct tm t; + time_t epochTime; + + t.tm_sec = RTCTimestampStruct.seconds; + t.tm_min = RTCTimestampStruct.minutes; + t.tm_hour = RTCTimestampStruct.hours; + t.tm_mday = RTCTimestampStruct.days; + // In epoch conversion, the months are 0-11 + // so the months is decremented + t.tm_mon = RTCTimestampStruct.months - 1; + t.tm_year = RTCTimestampStruct.years + YEAR_2000 - EPOCH_YEAR; + // Disabled daylight saving + // If daylight saving is not disabled, MinGW in VectorCAST + // may or may not calculate the value right + t.tm_isdst= 0; + +#ifdef _VECTORCAST_ + // MinGW in VectorCAST assumes the time is local while + // the time is in GMT so 8 hours is subtracted from the hour + // to simulate GMT for VectorCAST + t.tm_hour = t.tm_hour - LOCAL_TO_GTM_TIME_CONVERSION; +#endif + + epochTime = mktime(&t); + + return (U32)epochTime; +} + +/************************************************************************* + * @brief updateReadTimestampStruct + * The updateReadTimestampStruct function updates the time struct after every + * read + * @details + * Inputs : none + * Outputs : none + * @param none + * @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 setMibSPIBufferLength + * The setMibSPIBufferLength sets the MibSPI buffer length prior to every + * RTC transaction + * @details + * Inputs : length + * Outputs : ransferStatus (bool) + * @param none + * @return transferStatus (bool) + *************************************************************************/ +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_0)) & (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_0)) & (uint16)0x00FFU ); /* chip select */ + + transferStatus = TRUE; + } + else + { + transferStatus = FALSE; + } + + return transferStatus; +} + +/************************************************************************* + * @brief prepBufferForReadCommand + * The prepBufferForReadCommand sets the txBuffer for a read + * @details + * Inputs : length + * Outputs : none + * @param none + * @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 handleExecWaitForPostState + * The handleExecWaitForPostState checks whether POST has completed and what + * was the result of the POST test. It will either go to Idle of Fault + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +static RTC_EXEC_STATE_T handleExecWaitForPostState( void ) +{ + RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WAIT_FOR_POST; + + if ( RTCSelfTestState == RTC_SELF_TEST_STATE_COMPLETE && + RTCSelfTestResult == SELF_TEST_STATUS_PASSED ) + { + result = RTC_EXEC_STATE_IDLE; + } + else if ( RTCSelfTestState == RTC_SELF_TEST_STATE_COMPLETE ) + { + result = RTC_EXEC_STATE_FAULT; + } + + return result; +} + +/************************************************************************* + * @brief handleExecIdleState + * 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 : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +static RTC_EXEC_STATE_T handleExecIdleState( void ) +{ + RTC_EXEC_STATE_T result = RTC_EXEC_STATE_IDLE; + + if ( hasWriteToRTCRequested ) + { + result = RTC_EXEC_STATE_WRITE; + } + else if ( hasWriteToRAMRequested ) + { + result = RTC_EXEC_STATE_PREP_RAM; + } + else if ( hasReadFromRAMRequested ) + { + result = RTC_EXEC_STATE_PREP_RAM; + } + else if ( timeCounter == TIMER_COUNTER_TO_REQUEST_READ ) + { + prepBufferForReadCommand( RTC_GENERAL_BUFFER_LENGTH ); + result = RTC_EXEC_STATE_READ; + } + else + { + timeCounter++; + } + + return result; +} + +/************************************************************************* + * @brief handleExecWriteState + * The handleExecWriteState writes timestamp to RTC + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +static RTC_EXEC_STATE_T handleExecWriteState( void ) +{ + RTC_EXEC_STATE_T result = RTC_EXEC_STATE_WRITE; + BOOL isStatusOk = serviceRTC( txBuffer, rxBuffer, RTC_TIMESTAMP_BUFFER_LENGTH ); + + if ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + { + // Reset the counter to start with the new read + timeCounter = 1; + hasWriteToRTCRequested = FALSE; + result = RTC_EXEC_STATE_IDLE; + } + else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) + { + result = RTC_EXEC_STATE_FAULT; + hasWriteToRTCRequested = FALSE; + } + + return result; +} + +/************************************************************************* + * @brief handleExecPrepRAMState + * The handleExecPrepRAMState prepares the RAM for read or write + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +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 ) + { + result = RTC_EXEC_STATE_FAULT; + } + + return result; +} + +/************************************************************************* + * @brief handleExecWriteToRAMState + * The handleExecWriteToRAMState writes to RAM + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +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 ) + { + result = RTC_EXEC_STATE_IDLE; + RTCRAMStatus = RTC_RAM_STATUS_COMPLETE; + hasWriteToRAMRequested = FALSE; + } + else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) + { + result = RTC_EXEC_STATE_IDLE; + RTCRAMStatus = RTC_RAM_STATUS_FAILED; + hasWriteToRAMRequested = FALSE; + } + + return result; +} + +/************************************************************************* + * @brief handleExecReadFromRAMState + * The handleExecReadFromRAMState read from RAM + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +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 ) + { + result = RTC_EXEC_STATE_IDLE; + RTCRAMStatus = RTC_RAM_STATUS_COMPLETE; + hasReadFromRAMRequested = FALSE; + } + else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) + { + result = RTC_EXEC_STATE_IDLE; + RTCRAMStatus = RTC_RAM_STATUS_COMPLETE; + hasReadFromRAMRequested = FALSE; + } + + return result; +} + +/************************************************************************* + * @brief handleExecReadState + * The handleExecReadState reads timestamp from RTC. The function calls + * other functions to update the time struct and convert the latest time + * to epoch + * @details + * Inputs : none + * Outputs : result (RTC_EXEC_STATE_T) + * @param none + * @return result (RTC_EXEC_STATE_T) + *************************************************************************/ +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 ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + { + if ( isRTCFunctional() ) + { + updateReadTimestampStruct(); + lastEpochTime = convertTime2Epoch(); + timeCounter = 1; + result = RTC_EXEC_STATE_IDLE; + } + else + { + result = RTC_EXEC_STATE_FAULT; + } + } + else if ( RTCServiceState == RTC_SERVICE_COMPLETE ) + { + result = RTC_EXEC_STATE_FAULT; + } + + return result; +} + +/************************************************************************* + * @brief handleSelfTestStart + * The handleSelfTestStart calls another function to prepare the txBuffer + * for a read and sets the state to control registers + * @details + * Inputs : none + * Outputs : result (RTC_SELF_TEST_STATE_T) + * @param none + * @return result (RTC_SELF_TEST_STATE_T) + *************************************************************************/ +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; + prepBufferForReadCommand( RTC_GENERAL_BUFFER_LENGTH ); + result = RTC_SELF_TEST_STATE_CHECK_CTRL_REGS; + + return result; +} + +/************************************************************************* + * @brief handleSelfTestCheckCtrlRegs + * 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 : none + * Outputs : result (RTC_SELF_TEST_STATE_T) + * @param none + * @return result (RTC_SELF_TEST_STATE_T) + *************************************************************************/ +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 ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + { + if ( isRTCFunctional() ) + { + U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; + RTCPreviousSecond = RTCCurrentSecond; + + result = RTC_SELF_TEST_STATE_WAIT_FOR_FIRST_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 handleSelfTestWaitForFirstSecond + * 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 : none + * Outputs : result (RTC_SELF_TEST_STATE_T) + * @param none + * @return result (RTC_SELF_TEST_STATE_T) + *************************************************************************/ +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 ( RTCServiceState == RTC_SERVICE_COMPLETE && isStatusOk ) + { + if ( isRTCFunctional() ) + { + U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; + + if ( RTCCurrentSecond != RTCPreviousSecond ) + { + RTCPreviousSecond = RTCCurrentSecond; + 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 handleSelfTestWaitForSecondSecond + * 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 : none + * Outputs : result (RTC_SELF_TEST_STATE_T) + * @param none + * @return result (RTC_SELF_TEST_STATE_T) + *************************************************************************/ +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 ) + { + if ( isRTCFunctional() ) + { + U32 RTCCurrentSecond = rxBuffer[ RTC_SECONDS_INDEX ]; + + if ( RTCCurrentSecond != RTCPreviousSecond ) + { + result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; + } + } + 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 handleSelfTestCheckAccuracy + * 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 : none + * Outputs : result (RTC_SELF_TEST_STATE_T) + * @param none + * @return result (RTC_SELF_TEST_STATE_T) + *************************************************************************/ +static RTC_SELF_TEST_STATE_T handleSelfTestCheckAccuracy( void ) +{ + RTC_SELF_TEST_STATE_T result = RTC_SELF_TEST_STATE_CHECK_ACCURACY; + + if ( didTimeout( RTCSelfTestTimer, RTC_ACCURACY_TIMEOUT ) ) + { + U32 elapsedTime = calcTimeSince( RTCSelfTestTimer ); + + if ( elapsedTime > RTC_ACCURACY_TIMEOUT_TOLERANCE ) + { + RTCSelfTestResult = SELF_TEST_STATUS_FAILED; + } + else + { + RTCSelfTestResult = SELF_TEST_STATUS_PASSED; + } + + result = RTC_SELF_TEST_STATE_COMPLETE; + } + + return result; +} Index: RTC.h =================================================================== diff -u --- RTC.h (revision 0) +++ RTC.h (revision 6e0f785edb79d85bab667147793c4e47d7cabbf0) @@ -0,0 +1,60 @@ +/************************************************************************** + * + * Copyright (c) 2019-2019 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.h + * + * @date 27-NOV-2019 + * @author D. Navaei + * + * @brief RTC header file. + * + **************************************************************************/ + +#ifndef _RTC_H_ +#define _RTC_H_ + +#include "Common.h" + +typedef enum RTC_RAM_STATUS +{ + RTC_RAM_STATUS_IDLE = 0, + RTC_RAM_STATUS_IN_PROGRESS, + RTC_RAM_STATUS_BYTES_EXCEEDED, + RTC_RAM_STATUS_ILLEGAL_ADDRESS, + RTC_RAM_STATUS_FAILED, + RTC_RAM_STATUS_COMPLETE + +} RTC_RAM_STATUS_T; + +typedef enum RTC_RAM_STATE +{ + RTC_RAM_STATE_READY = 0, + RTC_RAM_STATE_BUSY + +} RTC_RAM_STATE_T; + +void initRTC( void ); + +void execRTC( void ); + +void setRTCTimestamp( U08 secs, U08 mins, U08 hours, U08 days, U08 months, U16 years ); + +U32 getRTCTimestamp( void ); + +SELF_TEST_STATUS_T execRTCSelfTest( void ); + +RTC_RAM_STATUS_T writeToRAM( U16 address, U16* data, U32 length ); + +RTC_RAM_STATUS_T readFromRAM( U16 address, U32 length ); + +RTC_RAM_STATUS_T getRTCRAMStatus( void ); + +RTC_RAM_STATE_T getRTCRAMState( void ); + +void getDataFromRAM( U16* externalBuffer, U32 length ); + +#endif