AVR Libc Home Page AVRs AVR Libc Development Pages
Main Page FAQ Library Reference Additional Documentation Example Projects

Additional notes from <avr/sfr_defs.h>
[<avr/sfr_defs.h>: Special function registers]

<avr/sfr_defs.h> ファイルはすべての <avr/ioXXXX.h> ファイルからインクルードされます。これは特殊機能レジスタを単なるCの変数や定数に見えるように定義するマクロを持っています。これは _SFR_ASM_COMPAT 定義によります。<avr/iom128.h> にある、どうやってそのようなマクロを定義するかについてのいくつかの例題も紹介します。

#define PORTA _SFR_IO8(0x1b)
#define TCNT1 _SFR_IO16(0x2c)
#define PORTF _SFR_MEM8(0x61)
#define TCNT3 _SFR_MEM16(0x88)

_SFR_ASM_COMPAT が定義されていないとき、CプログラムはPORTAなどの名前を直接Cの表現式内(代入式の左辺でも)に利用できるようになり、GCCはそれに対応します(可能なら短いI/O命令(in/outなど)を用います)。 __SFR_OFFSET 定義はこの場合は使われません。

_SFR_ASM_COMPAT を値 1 で定義すると、これらの名前(PORTAなど)を、IOレジスタのアドレスを表す単なる定数として用いるようになります。これはプリプロセッサによるアセンブラ(*.S)ソースファイルを扱う際には必要なことですが、__ASSEMBLER__ が定義される場合には自動的に定義されます。デフォルトでは、すべてのアドレス値はlds/sts命令で使えるメモリアドレスとして定義されます。これらのアドレス値をin/out値で用いるには、0x20を引いてやらなければなりません。

過去の互換性のために、古いアセンブラソースは、以下の記述を先頭に追加してください。

#define __SFR_OFFSET 0

これは自動的にI/O 空間アドレスから0x20を引いてくれます。しかしこれは裏技です。以下のように定義アドレスをマクロで変更するようソースを書き換えることを推奨します。この修正が終わったら __SFR_OFFSET 定義はもはや不要です。削除してください。

実際の例:このコードは、SPMCRが異なるアドレスにあるデバイス間で、ブートローダーで共用できるコードとなります。
※out命令が利用可能なら利用し、だめならsts命令を利用する。in/out用アドレスは_SFR_IO_ADDR()で、lds/sts用アドレスは_SFR_MEM_ADDR()で生成する。

<avr/iom163.h>: #define SPMCR _SFR_IO8(0x37)
<avr/iom128.h>: #define SPMCR _SFR_MEM8(0x68)
#if _SFR_IO_REG_P(SPMCR)
        out     _SFR_IO_ADDR(SPMCR), r24
#else
        sts     _SFR_MEM_ADDR(SPMCR), r24
#endif

SREGなど、対象IOアドレスがIOスペースに入っているとわかっていれば、 _SFR_IO_REG_P マクロで判定することなくin/out/cbi/sbi/sbic/sbis 命令が利用可能です。もし誤っていればアセンブラは"I/Oアドレスが0-0x3fの範囲外だ" と文句を言いますので、誤ったまま使用する危険はなく、安全といえます。

__SFR_OFFSETを定義しない場合 (その場合はデフォルト値0x20となります)、すべての特殊機能レジスタアドレスはメモリアドレスとなります(たとえばSREGは0x5f)。速度やコードサイズの要求が厳しくなくて、上記のような汚い記述が嫌いなら、このアドレス値を用いて常にlds/sts命令でメモリマップドIO方式のアクセスを行うことができます。しかし、これは __SFR_OFFSET != 0x20の時は使えません。そこで、(__SFR_OFFSET == 0x20) の場合のみ定義されるマクロを念のため組み込んでください。

        sts     _SFR_ADDR(SPMCR), r24

Cプログラムでは、_SFR_ASM_COMPAT__SFR_OFFSET の値により起こりえる3つの組み合わせへの対応がサポートされています。_SFR_ADDR(SPMCR)マクロはSPMCRレジスタのアドレスを得るのに用いられます(0x57 又は0x68、デバイスによって異なる)。


Automatically generated by Doxygen 1.4.1 on 23 Jan 2006.