【发布时间】:2018-05-02 18:52:24
【问题描述】:
这是我第一次使用 64 位 time_t 结构来做时间运算。编译器是 TI 针对 CC3220SF 的 C 编译器。
这是我的函数,应该将秒数返回到下一个事件:
#define ACQ_INTERVAL 1 // in minutes
time_t _lastAcquisition;
time_t _timeToAcquire(void)
{
time_t now = _getEpoch(); // from internal RTC
if (_lastAcquisition == 0) _lastAcquisition = now;
time_t diff = now - _lastAcquisition; // seconds since last acquisition
time_t next = ACQ_INTERVAL * 60;
UART_PRINT("Interval is %lld s\r\n", next);
UART_PRINT("Current epoch is %lld, last acquisition was %lld, next one in %lld s\r\n", now, _lastAcquisition, next - diff);
return next - diff; // seconds to next acquisition
}
UART_PRINT 只是 printf 的包装器。
这里是_getEpoch() 函数:
time_t _getEpoch(void)
{
_i16 ret;
_u8 pConfigOpt = SL_DEVICE_GENERAL_DATE_TIME;
_u16 pConfigLen = sizeof(SlDateTime_t);
SlDateTime_t dateTime = {0};
ret = sl_DeviceGet(SL_DEVICE_GENERAL, &pConfigOpt, &pConfigLen, (unsigned char *) &dateTime);
ASSERT_ON_ERROR(ret);
struct tm t;
time_t t_of_day;
t.tm_year = dateTime.tm_year - 1900;
t.tm_mon = dateTime.tm_mon - 1;
t.tm_mday = dateTime.tm_day;
t.tm_hour = dateTime.tm_hour;
t.tm_min = dateTime.tm_min;
t.tm_sec = dateTime.tm_sec;
t.tm_isdst = -1;
t_of_day = mktime(&t);
return t_of_day;
}
通常它工作正常,但有时我会得到一些奇怪的输出:
间隔为 60 秒
当前epoch是1511088032,最后一次采集是1511086500,下一次采集是18446744073709550144秒
显然有问题。差值应该是 1532。 此外,这个巨大的数字看起来像是 2^64 - x。但是 x 应该是 1742 ......我不明白它可能来自哪里。
我仔细检查了time_t的定义:
typedef long long __time64_t;
#if defined(_TARGET_DEFAULTS_TO_TIME64) || (__TI_TIME_USES_64) && __TI_TIME_USES_64)
typedef __time64_t time_t;
#else
typedef __time32_t time_t;
#endif
__TI_TIME_USES_64 已定义并设置为 1(IDE 向我显示#if 的第一部分已启用)。
【问题讨论】:
-
你能保证函数
mktime()支持64位吗?听起来好像发生了 32 位环绕。 (如果某处 64 位数字转换为 32 位,然后又转换回 64 位,由于 32 位中的上溢/下溢和符号扩展,您可能会得到令人惊讶的结果。)此外,如果time_t意外地是 32 位,而您 @987654332 @ 和"%lld"它考虑了 4 个额外的“随机”字节。为了消除疑虑,我会在适当的位置添加assert(sizeof (time_t) == 8);(如果assert不可用,则打印出来)。 -
mktime()定义如下:static __inline time_t mktime(struct tm *tptr) { return __mktime64(tptr); } -
您的
lastAcquisition变量或timeToAcquire()函数是否被多个线程/任务同时调用?您确定您的代码不存在竞争条件或线程安全问题吗? -
我没有使用 RTOS,所以我只有一个线程。我不会从 ISR 调用任何东西。此外,两者都只被引用一次,
lastAcquisition在同一函数中调用timeToAcquire()之前设置了几行。 -
time_t是某种算术类型。与其猜测它匹配long long,不如说清楚。UART_PRINT("%lld\n", now, (long long) (next - diff));如果这不起作用,那么“UART_PRINT 只是 printf 的包装器。”为 false 或printf()不合规。