電子工作

PIC16F拡張版

最近よく使われている新世代のPIC「Enhanced Mid-Range CPU」。おなじみのPIC16Fシリーズ(14ビットコア)の改良版について調べました。

周辺機能が強化され、集積度が上がったので、メモリー(ROM/RAM)や周辺回路が盛り沢山なのですが、ここでは、主にCPUの機能について、マニュアルを元に書いておきます。


割り込み機能が改善された

従来は割り込みの出入り口では、最低限の事しか行われませんでしたが、改善されました。

従来、割り込み時に行われていたのは、割り込み禁止フラグの設定と戻りアドレスのセーブだけ。STATUSの退避とか、普通最低行われそうなことも行われていなかったし、STATUS変更無しに行える命令があまりないので、割り込みのプロローグとエピローグは、とっても変な処理を書かざるを得ませんでした。

今回の変更では、主だったレジスタ( W,STATUS,BSR,FSR0,FSR1,PCLATH )が自動退避されるようになりました。退避はスタックに行うのではなく、シャドーレジスタに行われる方法。切り替えで済むので、時間がかからないし、多重割り込みも、多分、しないので、妥当な選択でしょう。

あの変な割り込みコードは書かなくて済むようになったわけです。

そうそう、スタックも16段に増えました。


データメモリのバンク管理が変わった

大きな変更の最初は、専用のバンク切り替えレジスタが備わったこと。容量128バイトのバンクが32個(もちろんチップによって実装ページ数は違いますが)。従来はSTATUSレジスタにあったビットでバンクを切り替えていたのですが、今回は BSRレジスタで切り替えます。

バンクの構成もすっきりして、バンクの先頭(00H-1FH)がコアレジスタと機能レジスタ領域、真ん中(20H-6FH)が汎用メモリ、末尾(70H-7FH)がコモン領域(どのバンクからも同じレジスタ)です(ただし、バンク32は特殊で割り込み時の退避用シャドーレジスタが置かれています)。

コアレジスタは、普通のCPUならば内蔵レジスタとでも言うべきレジスタで、全部で12本あります(INDF0,INDF1,PCL,STATUS,FSR0L,FSR0H,FSR1L,FSR1H,BSR,WREG,PCLATH,INTCON)。どのバンクからも同じアドレスでアクセスできます。

機能レジスタ(Special Function Registers)は、デバイス制御のためのレジスタで、バンクごとに様々な機能が置かれています。当然、チップが異なれば実装も変わります。

汎用メモリは、普通のRAM。これも、チップによってサイズが変わる部分。バンクの若い方から詰めて実装されているようです。

コモン領域は、各バンク16バイトを占めていますが、すべてが、バンク0の最後の16バイトと同じものです。バンク切り替えに関係なく使いたいような作業域をここに置きます。


間接アドレッシングが強化された

間接アドレッシングに使うFSRが二本になりました。FSRは2バイトの大きさになり、すべてのデータメモリを指定できるようになりました。STATUSレジスタのお世話にならなくて済むのは嬉しいです

FSRが二つだから、入力、出力用にインデックスレジスタとして使えます。また、限られた命令だけですが、自動INC / 自動DEC ができるようになったし、FSR+オフセットでアドレスできます。FSRの2バイトにまとめてオフセット演算もサポートされて、とても便利になりました。

FSRは2バイトなので、0000h〜ffffhの広いアドレスが分不相応に割り付けられています。この広大なアドレス空間を利用して、ちょっと複雑で便利なマッピングがされています。

細かく内容を眺めてみます。

通常のデータメモリ空間

BSRとレジスタアドレスの組み合わせで指定するアドレスと同じものをFSR(L,H)で指定します。ただし、ちょっと変換が必要。というのは、レジスタアドレス空間は7ビットしかないので、連続アドレスにするために、全体を右詰めしてアドレスを指定しなければなりません。まぁ、理屈なんですけど、気をつけなきゃね。

FSRnLには、7ビットのレジスタアドレスと、最上位ビットにBSRの最下位ビットをセット。FSRnHには、BSRを右シフトしてからセット。ということになります。

連続アクセス可能なデータメモリ空間

汎用データメモリを連続領域としてFSRを通じてアクセスできるようになりました。汎用のデータメモリ(レジスタ)は各バンクの真ん中に80バイトあるのですが、通常のデータメモリ空間では飛び飛びの位置になっています。これでは、80バイトを越える連続領域を素直に扱えません。これを飛び飛びではなく、連続領域としてアクセスできるようになりました。200バイトの連続領域など、従来はできなかったことができるようになったわけです。

実現方法はワイルドで、問題の各バンクの真ん中80バイトを取り出して、バンクの順に並べてしまうというもの。これが、FSRのアドレス2000h〜29afhに割り付けられました。容量は最大で31バンク分。最後のバンクはシャドーレジスタに使っているため除外されているようです。

便利になった反面、通常のアクセスアドレスと、この連続アクセスではアドレスが違うので、アドレスの変換など、面倒なトラブルも起きそうな気がします。バッファ以外では難しいかも。

プログラムメモリ空間

プログラムメモリの下位バイトも、FSRから間接指定で読めるようになりました。プログラムメモリからデータを取り出すのは、結構面倒なプログラムを書いていたのですが、普通に読み出しできます。まるでPICではなくなったみたい。

アドレスの指定は簡単で、プログラムメモリの(ワード)アドレスの最上位ビットを1にしたものをFSRにセットするだけです。


プログラムメモリの扱いは相変わらず?

データメモリはバンク切り替えがすっきりしたのですが、プログラムメモリの方は、あまり改善されていません。Goto/Call命令では相変わらずPCLATHの上位部分を使うので、遠くに飛ぶときは気をつけなければいけないのは、従来のとおり。プログラム空間そのものは32KWに拡張されたのは嬉しいのですが、扱いにくいさは以前のまま。2KBの壁は意識せざるを得ません。

といっても何点かの改善はなされています。


スタックが読み書きできる

スタックが16段になり、読み書きができるようになりました。

STKPTR が現在のスタックトップのアドレスを保持し、 TOSH / TOSL で現在のスタックトップをアクセスします。

STKPTR は、CALL / CALLW 命令の実行、または、割り込みの発生で、+1 、つまり増加し、RETURN / RETLW / RETIE などで -1、すなわち、減少します。

STKPTRは、5ビットの値を持ちます。1ビット多いのですが、これはスタックが存在しない状態(10h〜1fh)を表現するために余分なビットがついているからです。

STKPTRのリセット直後の値は、1fh。スタックは空ですからこれでいいわけです。最初のCALL が行われると、スタックの00hに戻りアドレスが詰まれ、STKPTRの値は 1fh +1 → 00h となります。

スタックの段数は増えたとはいえ、16段しかないので、ローカル変数のスタックフレームのような使い方はできません。戻りアドレスの調整や、特殊な分岐などプログラムフローを触るときに便利でしょう。(これも、PICが苦手だった部分ですね)


命令の強化

あって当然だったような命令が、ようやく追加されました。opcodeを見ると、バイナリベースで互換になるように、新しい命令はうまく隙間を縫ってコードを割り当てています(大抵は以前、NOP扱いだった部分です)。

メニューへ戻る
アルゴ算法堂へ戻る