使用C的嵌入式应用程序中的time()函数问题 [英] Problem with time() function in embedded application with C

查看:287
本文介绍了使用C的嵌入式应用程序中的time()函数问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ARM微控制器上使用time().达到此功能后,处理器将重新启动.

奇怪的是,当我处于调试模式时,代码可以完美运行,但是一旦我想以独立方式应用它,就会遇到重置.

我在俯视什么吗? 是否可以替代此功能?

代码部分就是这样

#include <sys/time.h>
#include <stdio.h>

void main (void)
{

   static time_t  rawtime = 0;

   rawtime = time (NULL);
}

解决方案

此功能是否可以替代?

可用时间源取决于硬件 ,而库则与硬件无关.因此,您必须自己提供具有硬件依赖性的库函数的实现,或者在某些情况下,它们可能包含在供应商提供的板级支持程序包(BSP)中.标头time.h提供了您的实现必须遵循的标准声明,而本例中的库提供了一个不完全起作用的默认实现.

如果您使用的是armcc(例如在Keil ARM MDK中使用的),则默认为 半托管 .那是它从开发主机而不是目标硬件那里获取时间.

半主机仅在连接到调试主机时进行调试时才起作用.但是,在这种情况下,time()应该返回-1,而不是重新启动处理器.此功能不是重新启动的原因-您可以通过删除它来证明这一点,并且重新启动仍然会发生.重新启动只是您显式地从main()返回-运行时还应该做什么?它会直接重新启动,也可能进入繁忙循环,在该循环中,看门狗定时器到期可能会重新启动它.这取决于您的C运行时环境实现.此外,其行为可能会有所不同,具体取决于是否连接了调试器.可以确定何时进行片上调试,并有条件地执行断点指令,例如中断调试器.

要使time()与目标硬件正确配合而不是使用半主机,必须重新实现它.它被定义为弱链接,您提供的任何实现都将覆盖默认设置,因此在项目中的某处必须具有一个功能:

#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; 
}

如果您的时间源需要任何形式的初始化才能起作用,则可以通过多种方式来做到这一点,例如:

  • 将初始化代码放在main()之前运行的运行时启动代码中.例如,您的启动代码可能具有称为SysInit()的函数或应在其中执行的类似功能.
  • 要求开发人员在使用time()之前执行必要的初始化.
  • 通过如下修改time()函数来初始化首次使用:

#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
        ...
    }

    ...


最后一种方法可能是最简单且最不容易出错的方法,并且不会使系统使用如果应用程序不使用time()可能不需要的代码.

您的示例代码包含stdio.h,但未使用它,但请注意,默认的stdio实现类似地依赖于半主机,并且可能需要 解决方案

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

这篇关于使用C的嵌入式应用程序中的time()函数问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆