我希望将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代码不是向编译器传达我想要做的最佳方式。
评论
答案 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
由于我没有相关设备,因此不知道时间安排。那些是核心依赖。