2012-04-26 3 views
3

avr-gccを使用してグローバル変数を未使用のI/Oレジスタ(PORTBなど)にバインドして、コードサイズを削減したいとします。私はこのトリックをAVRのアプリケーションノートAVR035(14ページ)で学びました。アプリケーションノートでavr-gccを使用して、未使用のAVR I/Oレジスタに変数をバインドする方法はありますか?

、彼らはIARコンパイラを使用し、I/Oのようにレジスタに変数をバインド:AVR-GCCで

__no_init volatile uint8_t [email protected]; 

、私は標準レジスタ(R3に変数をバインドすることができますこの場合は次の行を使用します)。

register uint8_t counter asm("r3"); 

これはI/Oレジスタでは機能しません。 I/Oレジスタに対してこれを行う方法はありますか?

+0

whoaこれは素晴らしいトリックです。しかし、1つの質問:STSとLDSの代わりにINとOUTを使用することで*コードサイズを増やすことを考えているとき、最初に組み立て全体をコーディングしないのはなぜですか? –

+0

アセンブリーはおそらくこのレベルのコードを微調整するのには良い考えです:-)私は一部のグローバル変数をI/Oレジスタに移動するだけで "速い"ゲインを期待していました。それは簡単ではないことが分かった。 – henning77

答えて

2

これはグローバル変数だけで、何のちょうど例えば、使用へUARTボーレートレジスタをこのようなものを使用した程度のために働くので:

#define myGlobalVariable UBRR 

はまた、この最適化は、それだけなら価値があることに注意してくださいほとんどのIOレジスタに直接ビットテスト命令があるので、たくさんのビットテストを行っています。 ああ、すべてのAVRがLDSとSTS命令を持っているわけではなく、単純なINとOUTに比べてコードサイズと速度の両方に大きな違いをもたらすZレジスタを介したアクセスSRAM ...

+0

はい、これは私が今やっていることです。しかし、私は、UBRRを使用すると実際にはSRAMのvarに比べてコードサイズが大きくなることに気付きました。たとえばを使用します。 PORTBは数バイトを節約しました。おそらく私はここでコンパイラが何をしているのかをもっと詳しく見る必要があります。 – henning77

+0

@ henning77 IOレジスタは通常は「volatile」です。つまり、コンパイラはソースコード内のすべての*読み込みまたは書き込みのIO操作を生成する必要があります。 (不揮発性の)変数を使用すると、コンパイラはレジスタ内の値をキャッシュすることでアクセスを最適化できます。例: 'i = 5; i = i + 1; i = i * 2; 'i 'にエイリアスされたIOレジスタからの3回の書き込みと2回の読み出しを必要とするが、グローバル不揮発性変数「i」への1回の書き込みのみを必要とする。 – JimmyB

関連する問題