アドレス空間の違いとレジスタの名前の違い
前回の記事で、ATtiny202はATmega328PやATtiny13Aとはレジスタの名前や機能の設定値からして違うという話をした。
私はAVRの開発は基本的にアセンブリ言語でしているので、どういう風にプログラムの記述が変わるのかアセンブリ言語で説明する。
以下、ATmega328PやATtiny13Aの事を「以前のマイコン」と表記する事がある。
まず、ATtiny202と以前のマイコンでは、レジスタのアドレスの振り方が違う。
データシートから抜粋した両者のメモリ配置図を見て欲しい。
- ATtiny202のメモリ配置 (データシートより引用)
- ATmega328Pのメモリ配置 (データシートより引用)
以前のマイコンではメモリアドレス0x0000~0x001Fに汎用作業レジスタのR0~R31が割り当てられ、I/Oレジスタのアドレスはその続きの0x0020からになっている。
対して、ATtiny202では汎用作業レジスタは別のメモリ空間に割り当てられており、I/Oレジスタはアドレス0x0000から始まっている。
そのおかげで、ATtiny202にはI/Oアドレスという少しややこしい概念がない。
そして、以前のマイコンでは各機能設定用のレジスタの一部がI/Oレジスタ領域にあるが、ATtiny202では各機能設定レジスタは基本的に拡張I/Oレジスタ領域にしかない。I/Oレジスタ領域にあるのは仮想のポート設定レジスタとCPU用レジスタ(ステータスレジスタ等)くらいだ。
レジスタの名前
ATtiny202のデータシートを読むと、各機能の制御用にCTRLAやCTRLBといったレジスタがある。
しかし、様々な機能で同じようにCTRLAやCTRLBという名前になっており、ソースコードにそのまま記述しても設定したい機能のレジスタを特定できない。
そこで、ATtiny202の様々なレジスタ等の定義値を記している”tn202def.inc”というファイルを開くと、例えばSPIのCTRLAレジスタは”SPI0_CTRLA”と定義されている。
この定義値はデータシートに書いてないので、データシートと合わせて”tn202def.inc”の中身を見ながらプログラムを記述する必要がある。
対して、以前のマイコンでは基本的に各機能のレジスタ名はデータシートに書いてある名前がそのまま使える。ATmega328Pのデータシートでは、SPIの設定をするレジスタは”SPCR”となっていて、ソースコードに”SPCR”と書けばプログラムはそのままアセンブルできる。
ATtiny202のタイマ
ATtiny202のタイマも、データシートを読むとかなり多機能なようだ。タイマAには標準動作モードと分割動作モードがあり、標準動作モードでは普通の16bitタイマなのだが、分割動作モードでは8bitタイマ2つとして使う事が出来るようだ。分割動作モードは今回は使用しておらず、データシートもちゃんと読んでいないのでこの記事では割愛する。
以前のマイコンでは、タイマの動作開始は制御レジスタにプリスケーラ設定値を書き込んだ時点だったが、ATtiny202ではCTRLAレジスタにENABLEというビットがあり、このビットに1を書き込む事でタイマは動作を開始する。
確かに、慣れれば「プリスケーラを設定した時点で動作開始」より「ENABLEビットに1を書き込んだ時点で動作開始」の方が直感的で分かりやすいかもしれない。
ATtiny202ではタイマに限らず、殆どの機能のCTRLAレジスタにENABLEビットがあり、このビットを1にすることでその機能が有効になる。
タイマオーバーフロー割り込みと割り込みベクタ
以前のマイコンでは、割り込みがかかると自動的にステータスレジスタのIフラグが0になり全割り込み禁止になる。また、割り込み要求フラグも自動的に解除される。
しかし、ATtiny202では、割り込みがかかった後の全割り込み禁止処理と割り込み要求フラグの解除が必要な場合は、プログラムに記述しなければならない。特別な理由がない限り、通常は記述しておいた方が良いと思われる。
割り込みがかかってもステータスレジスタの退避が自動で行われないのは以前のマイコンと同じなので、通常はこちらもプログラムに記述しておく必要がある。
また、ATtiny202のタイマAオーバーフロー割り込みベクタは0x0008なのだが、これも”tn202def.inc”に定義値が記載されており、”TCA0_OVF_vect”となっている。
この記事を書くために改めて確認したら、実は以前のマイコンのincファイルにも記載されていたが、知らずに今までは即値をそのまま使っていた。
ポート設定
以前のマイコンでは、ポート関連のレジスタは基本的にI/Oレジスタ領域0x0020~0x005F(I/Oアドレスでは0x0000~0x003F)の範囲内にあるが、ATtiny202では冒頭でも述べたように拡張I/Oレジスタ領域にある。例えば、ポートAの入出力方向を設定する”PORTA_DIR”レジスタは0x0400にある。
しかし、ポート設定へは頻繁にアクセスするし、ピンの値によって処理を分岐させる際等に使用するSBICやSBIS命令が使えないのはあまりにも不便という配慮なのか、仮想ポートというレジスタが用意されている。
例えば、”PORTA_DIR”に対応する仮想ポートレジスタは”VPORTA_DIR”で、アドレス0x0000だ。アドレス0x0000~0x001Fの間に入っているので、SBICやSBIS命令も使える。仮想ポートは入出力方向、出力値、入力値、割り込み要求フラグの4レジスタが用意されており、ポートAの場合それぞれ”VPORTA_DIR”, “VPORTA_OUT”, “VPORTA_IN”, “VPORTA_INTFLAGS”で、アドレスは0x0000~0x0003となっている。
これらへのアクセスは、本来のレジスタである”PORTA_DIR”, “PORTA_OUT”, “PORTA_IN”, “PORTA_INTFLAGS”(アドレスはそれぞれ0x0400、0x0404、0x0408、0x0409)へのアクセスと同じ結果になる。通常は仮想ポートの方へのアクセスで良さそうである。
当然、この4レジスタ以外のポート設定を変更したい場合は本来のアドレス0x0400以降のレジスタにアクセスするしかないのだが。
また、以前のマイコンより便利なレジスタがいろいろと増えていて、例えば今回のプログラムでも使用している”PORTA_OUTTGL”などがある。
このレジスタはその名の通り、PORTAの出力値を反転させるというものだ。トグルスイッチのようにON-OFFを切り替えるイメージがしやすい。
使い方は簡単で、ポートAの切り替えたいビットに1を書き込むだけだ。例えばポートAのビット7の出力値を切り替えたかったら”PORTA_OUTTGL”に0B1000000(0x80)を書き込めば良い。そうするとポートA7ピンの出力値が0なら1、1なら0になる。いちいち現在の出力値を確認する手間が省けて楽だ。
実は、同じ事はポートAの入力値を返す”PORTA_IN”レジスタの該当するビットに1を書き込むことでも出来、それは以前のマイコンでも実装されていた(“PINx”レジスタの該当するビットに1を書き込む)のだが、OUTTGLという名前の専用レジスタが用意されたのは、より直感的にプログラム出来て良いと思う。
ポート設定だけでもここには書き切れない程の多数の機能があるので、詳しくはデータシートを参照されたい。
次回は、ATtiny202で“Lチカ”してみた時のプログラムを説明する。
ピンバック: ATtiny202-SSNRで“Lチカ” | Tales of Black-Mant 2
ピンバック: 8ピンのAVRマイコンATtiny202-SSNRが熱い (ATtiny13Aとの比較) | Tales of Black-Mant 2