我在针对 AVR 的 C 中的毫秒延迟循环有问题。我avr-gcc 4.7.0
在从 Ubuntu 存储库获得的 Linux 上使用,并且我还尝试了新编译的 4.7.2。目标硬件是 XMEGA128A1,目前时钟频率为 2 MHz。
以下函数经常(但并非总是如此——在遇到麻烦之前我曾多次调用此函数)抱怨约束:
../common/spin_delay.h:64:9: warning: asm operand 3 probably doesn’t match constraints [enabled by default]
../common/spin_delay.h:64:9: error: impossible constraint in ‘asm’
如果我删除因此错误停止编译的特定调用,它也会抱怨操作数 0、1 和 2。
#define LOOPS_PER_MS ((CPU_CLK_HZ/1000)/4)
static inline void ms_spin(unsigned short ms) {
if (ms) {
__asm__ __volatile__ (
" ldi r24, %1 \n"
" ldi r25, %0 \n"
"1: ldi r26, %3 \n"
" ldi r27, %2 \n"
"2: sbiw r26, 1 \n"
" brne 2b \n"
" sbiw r24, 1 \n"
" brne 1b \n"
:
: "M" (ms >> 8),
"M" (ms & 0xff),
"M" (LOOPS_PER_MS >> 8),
"M" (LOOPS_PER_MS & 0xff)
: "r24", "r25", "r26", "r27"
);
}
}
然而,相同的代码在 Windows 上使用 WinAVR 编译得很好avr-gcc 4.3.3
,这让我认为这是从那时起内联汇编器的一些变化。
在我看来,这一切看起来都是正确的,因为 16 位 short 被分解为高字节和低字节并受“M”(8 位常量)约束,而它工作了几次这一事实排除了与硬定义的CPU_CLK_HZ
派生常量。问题操作数是 0-3 中的任何一个这一事实意味着它不是失败的特定 asm 操作数。
我也尝试使用这里n
推荐的约束,但错误仍然存在。