时间戳基于具有溢出计数器的硬件定时器

时间:2014-02-12 09:53:29

标签: timer embedded interrupt msp430

我想为基于msp430的平台实现时间戳功能。

我的目标是使用硬件定时器,并计算它溢出的次数,以生成一个长时间戳值(通常是溢出计数器的uint32,结合硬件定时器的uint16值)。

这就是我所拥有的:

  • 溢出计数器在中断时递增,
  • 每次请求时间戳时都会检查其值(这受到中断锁保护)。
  • 溢出计数器值与当前硬件计时器值组合成一个大的时间戳。

当我考虑到中断的时间时,我遇到了问题。


我的第一个天真实施:

uint16_t timer_value = timer_value_get();

__istate_t istate = interrupt_disable();
uint64_t overflow_count_local = overflow_count; // the volatile incremented on interrupt
interrupt_restore(istate);

return (overflow_count_local << 16u) + timer_value;    

在获取定时器值之后但在禁用中断之前发生溢出时,这将失败。 overflow_count_local将比分配timer_value时更大1。


我试图添加其他检查以检测此可能的中断

uint16_t timer_value = timer_value_get();

__istate_t istate = interrupt_disable();
uint16_t second_timer_value = timer_value_get();

uint64_t overflow_count_local = overflow_count; // the volatile incremented on interrupt
interrupt_restore(istate);

if (second_timer_value < timer_value) {
    // A HW timer overflow occured just before disabling interrupts.
    overflow_count_local--;
}

return (overflow_count_local << 16u) + timer_value;    

这不是要么工作,这次是因为定时器在禁用中断后可能已经溢出,但在分配second_timer_value之前。这会使overflow_count_local太少。


然而,我试图扭转局面,似乎总是有一个未涵盖的案例。是否有一种已知的方法可以使这项工作?

一些限制:

  • 计时器也用于其他功能(使用捕获/比较),但可能无法停止。
  • msp430的RTC模块可能不会用于此效果,因为它用于保持当天的实际时间。
  • 没有32位计时器可用。

2 个答案:

答案 0 :(得分:3)

以下算法无锁(无需中断禁用):

获取溢出然后定时器(按此顺序),直到溢出与定时器读取的任何一侧相同。

uint32_t hi ;
uint16_t lo ;
do
{
    hi = overflow_count ;
    lo = timer_value_get() ;

} while( hi != overflow_count )

return (hi << 16 ) | lo ; 

这通常应该最多进行零次或一次迭代,除非有异常长的上下文切换到另一个线程或中断,在此期间定时器再次溢出。

答案 1 :(得分:1)

也许是这样的。我认为不需要用这个来禁用中断。

timer_value_1 = timer_value_get();
overflow_count_snapshot = overflow_count;
timer_value_2 = timer_value_get();
if (timer_value_2 < timer_value_1)
{
    return (timer_value_2 + (overflow_count << 16)); // not the snapshot
}
else
{
    return (timer_value_2 + (overflow_count_snapshot << 16)); // you could use timer_value_1 or 2
}