前文
16 ビット I/O レジスタ (タイマー カウンター、ICR/OCR、ADC...) の上位部分と下位部分のアトミックで同時の読み取り/書き込みのために、AVR はシャドウ一時レジスタを使用することが知られています。例えばTCNT1
ATmega8 で読む:
uint8_t tl, th;
tl = TCNT1L; // tl <- TCNT1L, avr_temp <- TCNT1H (atomic)
th = TCNT1H; // th <- avr_temp
(ここavr_temp
に AVR 一時シャドウ レジスタがあります)。TCNT1H
だから、例えば最初に読むのは間違っている。
質問
次のようなコードで AVR-GCC を使用しても安全ですか?
uint16_t ticks;
ticks = TCNT1;
TCNT1 = 0x1234;
AVR-GCC は常にこれらの操作に対して適切なコードを生成しますか?
(「いいえ」のようです(GCCは、が指すメモリへのアクセスがTCNT1
AVRシャドウレジスタを使用することをどのように認識していますか?)、avr-libcはマクロTCNT1を定義し、TCNT1H、TCNT1Lおよびavr-libcのFAQを直接使用することをお勧めしますTCNT1
。迷っています。)
AVR-GCC v4.7.2 をテストしましたが、常に正しいコードを生成しているようです。「TCNT1 |= 1」と書いても、次のように適切なコードが生成されます-O3
。
$ avr-gcc -std=c99 -mmcu=atmega8 -S -O3 -o - 1.c
...
in r24,0x2c // TCNT1L
in r25,0x2c+1 // TCNT1H
ori r24,1
out 0x2c+1,r25
out 0x2c,r24
...
TCNT1
普通の16ビット変数で変えてもコードは同じです。TCNT1
では、「GCC は、 が指すメモリへのアクセスが AVR シャドー レジスタを使用することをどのように認識するのでしょうか?」-- デフォルトでは、 16 ビット変数にアクセスするときは常にシャドー レジスタを想定しているようです。