3

前文

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は、が指すメモリへのアクセスが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 ビット変数にアクセスするとき常にシャドー レジスタを想定しているようです。

4

2 に答える 2

3

どうやって知っているのかはわかりませんがTCNT1、何十ものプログラムで問題なく直接使用しました。リンクしたFAQは、私が読んだすべてのチュートリアルと同様に、そのようにすることを提案しています。

FAQ のポイントは、2 つのレジスタの書き込みの間に割り込みが発生しないようにすることです。avr-gcc はそれらに正しい順序でアクセスするコードを生成しますが、それらの間で割り込みが発生しないことを保証することはできません。

于 2013-01-05T13:17:46.467 に答える