前文
16 ビット I/O レジスタ (タイマー カウンター、ICR/OCR、ADC...) の上位部分と下位部分のアトミックで同時の読み取り/書き込みのために、AVR はシャドウ一時レジスタを使用することが知られています。例えばTCNT1ATmega8 で読む:
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は、が指すメモリへのアクセスがTCNT1AVRシャドウレジスタを使用することをどのように認識していますか?)、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 ビット変数にアクセスするときは常にシャドー レジスタを想定しているようです。