I am working on microcontroller TC23X (Infineon), and my "time()" function is always returning the maximum value 0xFFFFFFFF I am using the compiler "Tasking VX Toolset for Tricore V6.3r1"
Can someone please help me how to resolve above issue. so that time() returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds
I have tried these methods "time(NULL), time(0) and time(&Var)"
CodePudding user response:
Because the availability of time/date is specific to the the hardware platform, time()
is provided as a default implementation that simply returns "not available" (-1).
If your platform as a time/date source such as an RTC, GNSS or NTP client, then you can override the default implementation to utilise that source, simply by defining a replacement function - for example:
time_t time( std::time_t *timeptr )
{
time_t epoch_time = 0 ;
struct tm time_struct = {0} ;
// Your code to get RTC data in a tm struct here
...
struct tm timedate = {.tm_mday = ...,
.tm_mon = ..., // January == 0
.tm_year = ..., // Years since 1900
.tm_hour = ...,
.tm_min = ...,
.tm_sec = ...
} ;
// Convert tm struct to UNIX epoch time
epoch_time = std::mktime( &time_struct ) ;
if( tp != 0 )
{
*timeptr = epoch_time ;
}
return epoch_time ;
}
A more efficient method is to initialise a 1Hz periodic counter with the RTC source on first use, then thereafter return the value of the counter:
volatile static time_t epoch_time = TIME_MAX ;
void timer_ISR_1Hz( void )
{
epoch_time ;
}
time_t time( std::time_t *timeptr )
{
if( epoch_time == TIME_MAX )
{
struct tm time_struct = {0} ;
// Your code to get RTC data in a tm struct here
...
struct tm timedate = {.tm_mday = ...,
.tm_mon = ..., // January == 0
.tm_year = ..., // Years since 1900
.tm_hour = ...,
.tm_min = ...,
.tm_sec = ...
} ;
// Convert tm struct to UNIX epoch time
epoch_time = std::mktime( &time_struct ) ;
// Start 1Hz timer here
...
}
time_t t = epoch_time ;
// Convert tm struct to UNIX epoch time
if( tp != 0 )
{
*timeptr = t ;
}
return t ;
}
The above solution works where you have no RTC source if you initialise to the epoch time from user supplied time/date input after power-on.
When reading RTC hardware (or any other time source) you need to make sure the time is consistent; it is possible for example to read the 59 seconds, just as it rolls over to 00 seconds, and then read the minutes and so end up with say 20 minutes 59 seconds, when it should be 19 minutes 59 seconds, or 20 minutes 00 seconds. The same applies to the roll-over of minute, hour, day, month and year.
You might further wish to synchronise the second update with UTC seconds via a GNSS 1PPS or NTP for example. It depends on what level of precision you might require.
CodePudding user response:
Even though you have that "autosar" tag set, the TC23x specs seem to only allow AUTOSAR Classic to be run on them. But, in that and the case of automotive, I wonder, why it is actually for you to be allowed to use time() function at all.
First of all, the part of the C-standard, that a freestanding environment has to support, does certainly not include time.h.
Second, only AUTOSAR Adaptive only supports a very small subset of POSIX, the POSIX profile PSE51 defined by IEEE1003.13
.
But as stated above, AUTOSAR Adaptive is not really something to run on this TC23x.
So, in general i would suggest to you, forget about all C-Standard library functions to use. Look into the AUTOSAR components, their features and interfaces.
Maybe you should actually look for AUTOSAR features, like the StbM, in order to first of all have support for a synchronized global time base, which then distributed through the vehicle over several possible TimeGateways to your ECU.
The StbM for example has to be configured like the rest of your AUTOSAR stack from your SystemDescription (GlobalTimeDomains and TimeMaster/TimeSlave/TimeGateway), and a reference to a pure local timer (e.g a MCAL GPT timer) as the actual local timebase, even if not yet synchronized.
Then you can use for example this StbM interface:
Std_ReturnType StbM_GetCurrentTime(
StbM_SynchronizedTimeBaseType timeBaseId,
StbM_TimeStampType* timeStamp,
StbM_UserDataType* userData)
/** Variables of this type are used for expressing time stamps including relative time and
* absolute calendar time.
* The absolute time starts from 1970-01-01. <----
* 0 to 281474976710655s == 3257812230d [0xFFFF FFFF FFFF]
* 0 to 999999999ns [0x3B9A C9FF]
* invalid value in nanoseconds: [0x3B9A CA00] to [0x3FFF FFFF]
* Bit 30 and 31 reserved, default: 0
*/
typedef struct {
StbM_TimeBaseStatusType timeBaseStatus;
uint32 nanoSeconds;
uint32 seconds; // lower 32bit of 48bit seconds
uint16 secondsHi; // higher 16bit part of 48bit seconds
} StbM_TimeStampType;
// There is also an "extended" version of the function and structure available
// using uint64 type instead the split uint32/uint16 for the seconds part
typedef uint8 StbM_TimeBaseStatusType;
// Bit 0 (LSB): 0x00: No Timeout on receiving Synchronisation Messages
// 0x01: Timeout on receiving Synchronisation Messages
#define TIMEOUT 0x01
// Bit 2 0x00: Local Time Base is synchronous to Global Time Master
// 0x04: Local Time Base updates are based on a Time Gateway below the Global Time Master
#define SYNC_TO_GATEWAY 0x04
// Bit 3 0x00: Local Time Base is based on Local Time Base reference clock only (never synchronized with Global Time Base)
// 0x08: Local Time Base was at least synchronized with Global Time Base one time
#define GLOBAL_TIME_BASE 0x08
// Bit 4 0x00: No leap into the future within the received time for Time Base
// 0x10: Leap into the future within the received time for Time Base exceeds a configured threshold
#define TIMELEAP_FUTURE 0x10
// Bit 5 0x00: No leap into the past within the received time for Time Base
// 0x20: Leap into the past within the received time for Time Base exceeds a configured threshold
#define TIMELEAP_PAST 0x20
like this:
const StbM_SynchronizedTimeBaseType timeBaseId = YOUR_TIME_DOMAIN_ID; // as configured in the AUTOSAR config tool
StbM_TimeStampType timeStamp;
StbM_UserDataType userData; // up to 3 bytes transmitted from TimeMaster (systemdependent)
Std_ReturnType ret;
SchM_Enter_ExclusiveArea_0();
ret = StbM_GetCurrentTimer(timeBaseId, &timeStamp, &userData);
SchM_Exit_ExclusiveArea_0();
if (ret == E_NOT_OK) {
// Failure Handling and maybe report Error
// Is StbM and AUTOSAR Stack ok and running?
// Was this the correct timeBaseId?
} else {
if (timeStamp.timeBaseStatus & TIMEOUT) {
// TimeSync messages not received --> running further on local time (time since ECU was turned on)
}
if (timeStamp.timeBaseStatus & SYNC_TO_GATEWAY) {
// Synced to gateway, but not the global time master --> synchronized to the gateways time
// (possible drift from that gateway itself, or time since gateway was turned on)
} else {
// if bit is not set, we are synchronized to the global time master
}
// ..
// work with timeStamp.seconds and timeStamp.nanoSeconds
If there is no StbM, or no synchronized timebase, usually the ECUs just run on their local time based since ECU power on, whenever that was.