Timer 计时器溢出竞争条件
我用的是一个带有16位定时器的微控制器。当前值可以从寄存器中读取。但是我需要一个32位计数器。每次计时器溢出时,它都会生成一个中断。我当前的解决方案类似于下面的代码。每当计时器溢出时,变量Timer 计时器溢出竞争条件,timer,overflow,microcontroller,Timer,Overflow,Microcontroller,我用的是一个带有16位定时器的微控制器。当前值可以从寄存器中读取。但是我需要一个32位计数器。每次计时器溢出时,它都会生成一个中断。我当前的解决方案类似于下面的代码。每当计时器溢出时,变量计数器\u high就会递增。当前计数器值被读取为计数器\u high和定时器寄存器的组合 volatile uint16_t counter_high = 0; uint32_t get_counter(void) { return (counter_high << 16) | time
计数器\u high
就会递增。当前计数器值被读取为计数器\u high
和定时器寄存器的组合
volatile uint16_t counter_high = 0;
uint32_t get_counter(void)
{
return (counter_high << 16) | timer->counter;
}
void timer_overflow(void)
{
counter_high++;
}
volatile uint16计数器高=0;
uint32获取计数器(无效)
{
返回(计数器)\高计数器;
}
无效计时器\u溢出(无效)
{
计数器_high++;
}
这似乎是可行的。但是我开始想如果执行get_counter()
时计时器溢出会发生什么?我可以将counter_high
的旧值与timer->counter
的新值结合起来,或者反之亦然
有防止此问题的最佳实践吗?在读取
计时器->计数器之前和之后读取计数器高位
。如果读取的计数器高位
的值没有更改,则您知道计时器->计数器
在读取之间没有滚动,因此您可以信任从读取的值ode>定时器->计数器
但是,如果在两次读取之间counter\u high
发生变化,则您知道timer->counter
在两次读取之间滚动了一段时间。这意味着您无法信任从timer->counter
读取的值,因为您不知道是在滚动之前还是之后读取它。但现在您知道timer->counter代码>最近才翻滚,这样您就可以再次阅读它,并知道它不会再次翻滚
uint32_t get_counter(void)
{
uint32_t first_counter_high = counter_high;
uint32_t counter_low = timer->counter;
uint32_t second_counter_high = counter_high;
if (first_counter_high != second_counter_high)
{
counter_low = timer->counter; // Read timer->counter again, after rollover.
}
return (second_counter_high << 16) | counter_low;
}
uint32获取计数器(无效)
{
uint32第一个计数器高=计数器高;
uint32\u t计数器\u low=计时器->计数器;
uint32秒计数器高=计数器高;
如果(第一个计数器高!=第二个计数器高)
{
计数器低=定时器->计数器;//翻转后再次读取定时器->计数器。
}
return(second_counter_high)您基本上希望读取低值,然后检查溢出。如果溢出,则调整高值并重新采样低值,您应该是安全的。或者您可以根据您希望最接近实时的函数调用的哪一端将低值设为零。