fad*_*bee 5 assembly arm cortex-m
我希望在不使用定时器的情况下将ARM Cortex M0 +延迟n个周期,并尽可能缩小代码尺寸.(我认为这要求使用装配.)
延迟0个周期很简单,没有代码.1个周期的延迟是单个NOP.延迟2个周期是两个NOP.
在什么时候(代码大小)开始循环有效?
最紧密的循环需要多少个循环?什么是设置时间?
发布回答说明:
以下C代码:
register unsigned char counter = 100;
while (counter-- > 0) {
asm("");
}
Run Code Online (Sandbox Code Playgroud)
当用gcc和-O3编译时给出:
mov r3, #100
.L5:
sub r3, r3, #1
uxtb r3, r3
cmp r3, #0
bne .L5
Run Code Online (Sandbox Code Playgroud)
这或者说明了手工编写ARM程序集仍然有用,或者(更有可能)上面的C代码不是向编译器传达我想要做的最好的方式.
评论?
代码将完全依赖于n是什么,以及它是否需要动态变量,但是考虑到M0 +核心的指令时序,为特定例程建立边界非常简单.
对于具有固定8位立即计数器的最小可能(6字节)完整循环:
movs r0, #NUM ;1 cycle
1: subs r0, r0, #1 ;1 cycle
bne 1b ;2 if taken, 1 otherwise
Run Code Online (Sandbox Code Playgroud)
与NUM=1我们得到了最少3个周期,加上每增加循环3次达NUM=255765次(当然,你可以有2 ^ 32次NUM=0,但似乎有点傻).这使得循环的下限在大约6个循环中是实用的.使用固定循环,可以很容易地在其中填充NOP(甚至嵌套循环)以延长每次迭代,并在之前/之后对齐循环长度的非倍数.如果您可以在需要开始等待之前安排在寄存器中准备好多次迭代,那么您可以丢失初始值mov并且具有3个或更多个周期的任意倍数,减去1.如果你需要一个可变延迟的单周期分辨率,初始设置成本会更高一些,以纠正余数(计算分支到NOP雪橇是我要为此做的)
我假设如果你处于周期关键时序点,你已经关闭了中断(否则会在另一个周期中抛出CPSID),并且你没有任何总线等待状态为指令添加额外的周期取.
至于尝试在C中做到这一点:事实上你必须破解空asm以防止"无用"循环被优化掉是一个提示.抽象的C机器没有"指令"或"循环"的概念,因此根本无法用语言可靠地表达它.试图依赖特定的C结构来编译成合适的指令是非常脆弱的 - 改变编译器标志; 升级编译器; 改变一些影响寄存器分配的远程代码,影响指令选择; 几乎任何事情都可能意外地改变生成的代码,所以我认为手动编码汇编是周期精确代码的唯一合理方法.
我能想到的最短的 ARM 循环如下:
mov r0, #COUNT
L:
subs r0, r0, #1
bnz L
Run Code Online (Sandbox Code Playgroud)
由于我没有相关设备,所以不知道时间。这些都是核心依赖的。