I am using time()
on an ARM micro-controller. The processor restarts as soon as it reaches this function.
What is strange is that when I am in debug mode the code works perfect but as soon as I want to apply it in standalone I encounter a reset.
Am I overlooking something?
Is there a replacement for this function?
the part of code is like this
#include <sys/time.h>
#include <stdio.h>
void main (void)
{
static time_t rawtime = 0;
rawtime = time (NULL);
}
Is there a replacement for this function?
The available source of time is hardware dependent, and the library is hardware independent. As such you have to provide implementations for library functions with hardware dependencies yourself, or they may be included in a vendor provided board-support package (BSP) in some cases. The header time.h provides the standard declaration your implementation must conform to, while the library in this case provides a default implementation that is not fully functional.
If you are using armcc (as used in the Keil ARM MDK for example), then the default time()
implementation uses semi-hosting. That is it obtains time from the development host rather then than the target hardware.
Semi-hosting will work only when debugging while connected to a debug host. However in that case time()
should return -1 rather than a processor restart. This function is not the cause of the restart - you could demonstrate that by removing it, and the restart will still occur. The restart is simply that you explicitly return from main()
- what else is the runtime supposed to do? It will either restart directly or it may enter a busy loop, where a watchdog timer expiry might restart it. It depends on your C run-time environment implementation. Moreover the behaviour may differ depending on whether the debugger is connected or not; it is possible to determine when the on-chip debug is active and to conditionally execute a break-point instruction for example to interrupt the debugger.
To have time()
work correctly with your target hardware rather than use semi-hosting, you must re-implement it. It is defined as a weak-link and any implementation you provide will override the default, so somewhere in your project you must have a function:
#include <time.h>
time_t time( time_t* timep )
{
int hour = 0 ;
int minute = 0 ;
int second = 0 ;
int day_of_month = 0 ;
int month = 0 ;
int year = 0 ;
// Your code here to fill time/date from clock source
...
// Normalise to time.h library epoch time_t (normally Unix epoch)
struct tm timeinfo;
timeinfo.tm_mon = month - 1 ; // check assumption here Jan = 0 in tm
timeinfo.tm_mday = day_of_month ;
timeinfo.tm_year = year + 100 ; // check assumption here years start from 1900 in tm
timeinfo.tm_hour = hour ;
timeinfo.tm_min = minute;
timeinfo.tm_sec = second;
// Convert to timestamp
time_t t = mktime(&timeinfo);
if( timep != NULL )
{
*timep = t ;
}
return t;
}
If your time source requires any kind of initialisation before it will work, you can do that in a number of ways, for example:
- Place the initialisation code in the run-time start-up code that runs before
main()
. For example your start-up code may have a function called SysInit()
or similar where you should do this.
- Require the developer to perform necessary initialisation before
time()
is used.
- Initialise on first use by modifying the
time()
function as below :
#include <time.h>
#include <stdbool.h>
time_t time( time_t* timep )
{
static bool initialised = false ;
if( !initialised )
{
initialised = true ;
// your clock source initialisation here
...
}
...
This last method is probably the simplest and least error prone and does not saddle the system with code that it might not need if the application does not use time()
.
Your example code includes stdio.h but does not use it, but note that the default stdio implementation similarly relies on semi-hosting, and may need re-targetting
First of all this isnt embedded code time.h
and stdio.h
are software libs. You should have some like this:
#include <arm/UART_some_lib.h>
#include <arm/RTC_some_lib.h>
static someStartupFunctions()
{
RTC_setRTC(...);
}
int main(void)
{
someStartupFunctions();
while(1)
{
//Main code here
}
return 0;
}
BUT on arm can run operating system but there wont be embadded programing.