如何在实现分析时处理溢出

时间:2017-11-19 01:56:42

标签: c arm cortex-m

我试图找到ARM处理器中给定代码块消耗的时间。为此,我使用Systick计时器,它基本上是一个计数器。

对于正常的代码块,我可以测量功能开始和功能结束之间的时间差,以了解测量的时间。但是,如果这段代码太长,我应该如何处理呢?

根据我的逻辑,我将使用我设计的公式如下所示:

time consumed=(no. of times overflow occured X start value)
 +(start value - end value)

P.S:起始值是最大值,而不是零,因为定时器是向下计数器。

我的推理是正确的还是我应该使用其他公式?

3 个答案:

答案 0 :(得分:0)

公式应该是正确的,前提是你考虑了一个周期内完成的最大刻度数。

假设整个周期中的刻度数是MAX_TICKS,那么时间(以刻度表示)是

nUnderflows * MAX_TICKS + start - end

在C中,可以看作是,例如

#define MAX_TICKS 32768

int nUnderflows;

// schematic function called by the system every tick
// (in a critical section)
void systick_callback() {
    if ( ! internal_counter--) {
       internal_counter = MAX_TICKS;
       nUnderflows++;
    }
}

int main() {
   int start,end;

   // small critical section to avoid a race condition
   block_interruptions(); // CLI
   nUnderflows = 0;
   start = systick();
   release_interruptions(); // STI

   my_timed_function();

   end = systick();
   int time = (nUnderflows * MAX_TICKS) + start - end;
   // * precedence is usually higher than of + / -, though
}

提供int在您的情况下可用,并且不会溢出。

答案 1 :(得分:0)

如果它是首次自由运行的计数器,则需要确保起始端(或根据向下或向上计数结束)。因此,如果它是16位计数器(起始端),则0xFFFF将成为等式的一部分。然后溢出次数0x10000将成为它的一部分并且如果启动

如果计时器是一个完整的32位然后你不需要一个掩码,虽然优化器应该照顾它,作为一种习惯虽然你应该记住,如果你不掩盖,那么起始端会产生错误数字丢掉了,很多都是翻滚。

答案 2 :(得分:0)

Cortex documentation表示这是一个24位定时器,它从存储在名为SYST_RVR的端口中的值开始递减计数。 (我猜你的意思是“起始值”。在问这样的问题时最好使用记录的术语。)当值从1转换为0时,会生成一个systick中断,SYST_RVR被重置,循环重复。

SYST_RVR值,中断处理程序等取决于处理器所在系统的操作系统,您没有提及,因此一般无法回答您的问题。

OS通常使用这种定时器架构来实现与线程抢占等时间相关的函数的系统心跳。但是没有标准模式。

显然你知道SYST_RVR的操作系统值。这确定了计时器到期的速率。在已经校准定时器的系统中,还有另一个寄存器SYST_CALIB,用于存储到期之间10ms所需的值。也许你的系统使用它?这意味着零之间只有10毫秒。

你的配方很好。

“溢出次数(实际上它们是下溢)”可能是最难的部分。你打算如何确定?似乎只有两种方法:1)拦截systick中断并使用它来递增你自己的计数器。或者现有的中断处理程序可能已经存在计数器。然后,您可以测量该值的变化。选项2):您可以在正在测量的代码中插入分析点,记录定时器值profile_buffer[++bufp] = <systick value>。您需要插入足够的这些以确保它们相隔不超过10毫秒(或者无论实际的倒计时时间是多少)。然后,您可以在代码完成运行后分析缓冲区内容,以确定总运行时间。当然,添加测试代码会增加运行时间。但是,systick中断处理程序可能会遇到同样的问题,具体取决于它的实现方式。