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"
);
}
}
avr-gcc 4.3.3
ただし、WinAVR を使用して Windows で同じコードを問題なくコンパイルできることから、それ以降、インライン アセンブラに何らかの変更が加えられたと思われます。
私の考えでは、16ビットのショートは上位バイトと下位バイトに分解され、「M」(8ビット定数)によって制約されるため、すべて正しいように見えますが、数回機能したという事実は問題を除外しますハード定義されたCPU_CLK_HZ
派生定数。問題のオペランドが 0 から 3 のいずれかであるという事実は、失敗しているのは特定の asm オペランドではないことを意味します。
ここn
で推奨されている制約も使用しようとしましたが、エラーは解決しませんでした。