我需要在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
...
答案 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
小于计数器周期的一半,这就不受包装计数器值的影响 - 无符号算术产生正确的时间增量。
请注意,由于您不需要以任何方式控制计数器的值,您可以在系统中使用任何此类计数器 - 即使它被用于其他目的(当然,因为它实际上正在运行)连续自由地,以一定的速度为您提供所需的定时分辨率。