如何在没有定时器的情况下将ARM Cortex M0 +延迟n个周期?

时间:2014-12-16 17:15:15

标签: assembly arm cortex-m

我希望将ARM Cortex M0 +延迟n个周期,而不使用具有最小代码大小的定时器。 (我认为这要求使用汇编。)

0个周期的延迟很简单,没有代码。 1个周期的延迟是单个NOP。 延迟2个周期是两个NOP。

在什么时候(代码大小)开始循环有效?

最严格的循环需要多少个循环?什么是设置时间?


发布回答说明:

以下C代码:

register unsigned char counter = 100;
while (counter-- > 0) {
  asm("");
}

使用gcc和-O3编译时给出:

    mov r3, #100
.L5:
    sub r3, r3, #1
    uxtb    r3, r3
    cmp r3, #0
    bne .L5

这或者说明了手工编写ARM程序集的目的,或者(更有可能)上面的C代码不是向编译器传达我想要做的最佳方式。

评论

2 个答案:

答案 0 :(得分:8)

代码将完全依赖于 n 是什么,以及它是否需要动态变量,但是给定the M0+ core's instruction timings,为特定例程建立边界非常简单。< / p>

对于具有固定8位立即计数器的最小可能(6字节)完整循环:

   movs  r0, #NUM    ;1 cycle
1: subs  r0, r0, #1  ;1 cycle
   bne   1b          ;2 if taken, 1 otherwise

NUM=1我们得到至少3个周期,在765个周期内每个额外的循环加上3个周期,直到NUM=255(当然,你可以从{{1}进行2 ^ 32次迭代但是,这似乎有点傻)。这使得循环的下限在大约6个循环中是实用的。使用固定循环,可以很容易地在其中填充NOP(甚至是嵌套循环)以延长每次迭代,并在之前/之后对齐循环长度的非倍数。如果您可以在需要开始等待之前安排在寄存器中准备好多次迭代,那么您可能会丢失初始NUM=0并且几乎有3个或更多个周期的任意倍数,减去1。如果你需要一个可变延迟的单周期分辨率,那么初始设置成本会更高一些,以便校正剩余部分(计算分支到NOP雪橇就是我为此做的事情)

我假设如果您处于关键周期时间点,那么您已经关闭了中断(否则会在mov某处投入另一个周期),并且你没有任何总线等待状态为指令提取添加额外的周期。

至于尝试在C中进行:事实上你必须破解一个空的CPSID以保持&#34;无用的&#34;从优化开始循环是一个提示。抽象的C机器没有&#34;指令&#34;的概念。或者&#34;周期&#34;因此根本无法用语言可靠地表达这一点。尝试依赖特定的C构造来编译成合适的指令是非常脆弱的 - 更改编译器标志;升级编译器;改变一些影响寄存器分配的远程代码,影响指令选择;几乎任何事情都可能意外地改变生成的代码,所以我说手工编码汇编是用于周期精确代码的唯一明智的方法。

答案 1 :(得分:3)

我能想到的最短的ARM循环如下:

mov r0, #COUNT
L:
subs r0, r0, #1
bnz L

由于我没有相关设备,因此不知道时间安排。那些是核心依赖。