为n个cpu周期添加延迟/什么都不做的最佳方法

时间:2017-06-20 11:59:11

标签: c arm embedded stm32 stm32f0

我需要在n个CPU周期的代码中添加一个延迟(~30)。 我目前的解决方案是下面的解决方案,它可以工作,但不是很优雅。

此外,必须在编译时知道延迟。我可以使用它,但如果我可以在运行时更改延迟,那将是理想的。 (如果有一些开销可以,但我需要1个周期的分辨率。)

我没有留下任何外围计时器,我可以使用它,所以它需要是一个软件解决方案。

do_something();
#define NUMBER_OF_NOPS   (SOME_DELAY + 3)
#include "nops.h"
#undef NUMBER_OF_NOPS
do_the_next_thing();

nops.h:

#if NUMBER_OF_NOPS > 0
    __ASM volatile ("nop");
#endif
#if NUMBER_OF_NOPS > 1
    __ASM volatile ("nop");
#endif
#if NUMBER_OF_NOPS > 2
    __ASM volatile ("nop");
#endif
...

3 个答案:

答案 0 :(得分:1)

在皮质设备中,NOP实际上没有任何意义。无法保证NOP会随时消耗。它们仅用于填充。我将有几个连续的NOP,它们将从管道中冲洗掉。

有关更多信息,请参阅Cortex-M0文档。 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDJJGFB.html

软件延迟在Cortex设备中非常棘手,您应该使用其他指令+可能的屏障指令。

使用ISB指令4个时钟+闪存访问时间,这取决于核心运行的速度。对于非常精确的延迟,将这部分代码放在SRAM中

答案 1 :(得分:1)

编辑:来自另一个SO Q& A here的答案更好。然而,它是在装配中,使用像SysTick这样的计数器的AFAIK是保证任何相似的循环精度的唯一方法。

编辑2:为避免计数器溢出,这将导致非常非常长的延迟,请在使用前清除SysTick计数器,即。 SysTick->VAL = 0;

原件:

Cortex-Ms有一个称为SysTick的内置定时器,可用于周期精确定时。

首先启用计时器:

SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
               SysTick_CTRL_ENABLE_Msk;

然后,您可以使用VAL寄存器读取当前计数。然后,您可以通过这种方式实现周期精确延迟:

int count = SysTick->VAL;
while(SysTick->VAL < (count+30));

请注意,由于循环中的加载,比较和分支,这会引入一些开销,因此最终的循环计数会稍微偏离,估计不会超过几个滴答。

答案 2 :(得分:-1)

您可以使用自由运行的向上计数器,如下所示:

uint32_t t = <periph>.count;
while ((<periph>.count - t) < delay);

只要delay小于计数器周期的一半,这就不受包装计数器值的影响 - 无符号算术产生正确的时间增量。

请注意,由于您不需要以任何方式控制计数器的值,您可以在系统中使用任何此类计数器 - 即使它被用于其他目的(当然,因为它实际上正在运行)连续自由地,以一定的速度为您提供所需的定时分辨率。