Timer 基于带溢出计数器的硬件定时器的时间戳

Timer 基于带溢出计数器的硬件定时器的时间戳,timer,embedded,interrupt,msp430,Timer,Embedded,Interrupt,Msp430,我想为基于msp430的平台实现时间戳功能 我的目标是使用硬件计时器,并计算其溢出的次数,以生成长时间戳值(通常为溢出计数器的uint32,与硬件计时器的uint16值组合) 这就是我所拥有的: 溢出计数器在中断时递增 每次请求时间戳时都会检查其值(这由中断锁保护) 溢出计数器值与当前硬件计时器值组合为一个大的时间戳 当我考虑到中断的时间时,我遇到了问题 我拥有的第一个天真的实现: uint16_t timer_value = timer_value_get(); __istate_t

我想为基于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;    
这一次也不起作用,因为在禁用中断后,但在分配
秒计时器\u值之前,计时器可能溢出。这会使
溢出\u count\u local
太少


然而,我试图扭转这一局面,似乎总是有一个案件没有涵盖。有没有一个已知的方法可以让这项工作

一些限制:

  • 计时器还用于其他功能(带有捕获/比较功能),可能不会停止
  • msp430的RTC模块可能不用于此目的,因为它用于保持一天的实际时间
  • 没有32位计时器可用

    • 可能是这样的。我认为没有必要用这个来禁用中断

      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
      }
      
      timer_value_1=timer_value_get();
      溢出计数\u快照=溢出计数;
      定时器_值_2=定时器_值_get();
      如果(计时器值\u 2<计时器值\u 1)
      {
      
      return(timer_value_2+)(overflow_count可能是这样的。我认为没有必要用它来禁用中断

      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
      }
      
      timer_value_1=timer_value_get();
      溢出计数\u快照=溢出计数;
      定时器_值_2=定时器_值_get();
      如果(计时器值\u 2<计时器值\u 1)
      {
      
      返回(计时器\u值\u 2+(溢出\u计数以下算法是无锁的(不需要中断禁用):

      获取溢出,然后使用计时器(按该顺序),直到溢出与计时器读取的任一侧相同

      uint32_t hi ;
      uint16_t lo ;
      do
      {
          hi = overflow_count ;
          lo = timer_value_get() ;
      
      } while( hi != overflow_count )
      
      return (hi << 16 ) | lo ; 
      
      uint32\t hi;
      uint16_t lo;
      做
      {
      hi=溢出计数;
      lo=定时器值获取();
      }while(hi!=溢出\u计数)
      
      返回(hi以下算法无锁(无需中断禁用):

      获取溢出,然后使用计时器(按该顺序),直到溢出与计时器读取的任一侧相同

      uint32_t hi ;
      uint16_t lo ;
      do
      {
          hi = overflow_count ;
          lo = timer_value_get() ;
      
      } while( hi != overflow_count )
      
      return (hi << 16 ) | lo ; 
      
      uint32\t hi;
      uint16_t lo;
      做
      {
      hi=溢出计数;
      lo=定时器值获取();
      }while(hi!=溢出\u计数)
      
      返回(问题是,我不确定分配是原子的,特别是因为<代码>溢出流计数是32位。如果分配不是原子的,中断发生在中间,结果可能会变得丑陋。如果TimeRealValue2.2TimeRealValue1,那么你应该忽略快照。但是很可能中断刚刚发生。o再次读取溢出计数应该是安全的(即,它在一段时间内不会再次改变)。我想你可以读取两次溢出计数来确定。如果定时器值>定时器值>1,那么就没有中断,溢出计数快照是好的。我明白了。
      溢出计数快照
      可能是胡说八道,但如果是,那么它就不会被使用。有趣的是,我不确定赋值是否是原子的,特别是如果代码不是原子的,中断发生在中间,则结果可能会变得丑陋。如果TimeRealValue2.2TimeRealValue1您应该忽略快照,但是它很可能发生了中断,因此再次读取溢出流应该是安全的。(也就是说,一段时间内不会再改变)。我想你可以读取两次溢出计数来确定。如果timer\u value\u 2>timer\u value\u 1,那么没有中断,溢出计数\u快照是好的。我明白了。
      overflow\u count\u snapshot
      可能是胡说八道,但如果是,那么它就不会被使用。有趣。不错。因为循环主体中两行的顺序很重要,我想将
      hi
      lo
      设置为volatile
      s是合适的。溢出计数
      已经是volatile了,所以这里不需要它,但是对于
      lo
      。@Gauthier:这不会有什么坏处。只是一个警告,只有在启用中断时,它才能正常工作(或者,更具体地说,如果此代码可由计时器IRQ中断)。通常情况下,MSP430(或任何微控制器)代码是中断驱动的,如果这是从中断处理程序中调用的,其中MSP430全局禁用中断,则您将具有与OP示例中相同的竞争条件(在获取时间戳期间发生硬件溢出,但无法调用IRQ以增加溢出计数,因为中断已禁用).很好。由于循环主体中两行的顺序很重要,我想将
      hi
      lo
      设置为volatile
      s?
      overflow\u count
      已经是volatile了,所以这里不需要它,但是对于
      lo
      。@Gauthier:这不会有什么害处。只是一个警告,只有当我中断被启用(或者,更具体地说,如果此代码可被计时器IRQ中断)。通常,MSP430(或任何微控制器)代码是中断驱动的,如果这是从中断处理程序中调用的,其中MSP430全局禁用中断,那么您将具有与OP示例中相同的竞争条件(在获取时间戳期间发生硬件溢出,但无法调用IRQ以增加溢出计数,因为中断已禁用)。