たまりば

パソコン・インターネット パソコン・インターネット三鷹市 三鷹市

ベースラインPICの注意点
2015年04月11日 23:36

PICマイコンは時代を追ってベースライン→ミッドレンジ→ハイエンドと進化してきたが、日本で有名になったPIC16F84がミッドレンジのせいか、ベースラインPICに関する日本語の情報が少ない。
そのためミッドレンジに慣れた者がベースラインを使おうとして戸惑うのをたまに見かける。
そこで、ミッドレンジからベースラインへのマイグレーションを念頭に、この2つの違いを解説したい。
今更ベースラインを使う意味があるかは微妙な所だが、安さで10F200や16F57を選ぶこともあるだろう。

PIC10F200: 現在秋月で35円、aitendoで30円。自分の知る限り最安のマイコン。
PIC16F57: 現在秋月で70円。I/Oピンが20本あり、3.5円/ピン。自分の知る限りI/Oピンあたり価格が最安のFlashマイコン。
(ワンタイムを含めるとI/Oが43ピンで8個400円のこいつに負ける→ H8S16ビットワンタイムマイコンHD64P2128PS20V(8個入))

見分け方

比較の前に、まずベースラインとミッドレンジの見分け方について。
型番で簡単に見分けられるのだが、これが知らないと分かりづらい。自分も最近まで知らなかった。
まずPICの型番を見ると先頭に10F, 12F, 16F, 18Fとある。(さらには17F, 24F, dsPIC30, dsPIC33, PIC32MXとあるがこれらは単純なので割愛する。Fの部分がLFやCやHVのものもあるが割愛する)
PICを分類するのにこの先頭の数字で分類されるのが一般的だが、実はこの数字はベースラインとミッドレンジの区別には役立たない。
12Fがベースライン、16Fがミッドレンジであるとする誤った記述をたまに見かけるが注意が必要だ。
(ただしハイエンドを見分けることはできる。18Fがハイエンドだ。)
ではどこで見分けるかというと、英字の次の桁。
これが(現在のところ、ごく一部の例外を除き)2か5ならばベースラインである。(また、ベースラインならば2か5である)
例えば10F222、16F54、12F509はベースラインであり、10F322、16F84、12F609はミッドレンジである。
(初期に命名法が確立していなかったと思しきPIC16C55Xというミッドレンジが存在する)
また後半の数字が1始まりで4桁以上ある12F1*,16F1*はEnhancedミッドレンジである。
また現在のところ数は少ないが、Enhancedベースラインというものも存在する。型番の規則はベースラインと同じだ。
現在存在するEnhancedベースラインはおそらく、12F529T39A, 12F529T48A, 16F527, 16F570の4つのみである。

なお先頭の数字10,12,16は、ピン数に対応している。6ピンが10、8ピンが12、14ピン以上が16だ。
(ただし通常のI/Oピン以外に特殊機能のピンがある場合これに従わない。例:12F529T39A)
(また今後8ピンも16Fになるようだ。例: 16F18313)
(ハイエンドの8ピンはどうなるかというと、今のところ存在しないが、実は発表だけされて発売されなかった18F010/020がある)


以下機能の違いを見ていく。

割り込み

ミッドレンジで追加された機能で最も重要と言える。
割り込みを使ったコードは全てポーリングに書き直すしかない。
割り込みがどうしても必要ならミッドレンジを使うしかないし、そうでなくとも割り込みの方が簡単に書けるならミッドレンジを使うのが身のためだ。
ただもしかするとウォッチドッグタイマ(WDT)によるリセットで割り込みの代用ができるかもしれない。

タイマーのオーバーフロー

ベースラインもミッドレンジもTMR0の機能は基本的には同じである。
ただし、ベースラインには割り込み機能が無いのに伴ってオーバーフローフラグも無い。
割り込みを使っていなくてもオーバーフローフラグを使っていたプログラムは書き直しが必要だ。
簡単な対処法として、TMR0を7bitのタイマーと考えて、最上位bitをオーバーフローフラグの代わりに使う方法が考えられる。
タイマーが1周する前にチェックする必要がある点を除けば同様のプログラムが使える。
またはクロック単位できっかり合わせたいなら例えばこんな感じ。
synch:
    btfss TMR0,7
    goto $-1
    btfsc TMR0,7
    goto $-1
    decf TMR0,W
    addwf PCL,F
    nop
    nop
    nop
when:

スリープからの起床

ベースラインもミッドレンジもSLEEP命令によるスリープ機能は持っているが、起床時の動作が異なる。
ミッドレンジではスリープから起床するとSLEEP命令の直後から実行を再開する。(加えてその前に割り込みを掛けることもできる)
それに対しベースラインではスリープからの起床はリセットと同等であり、SLEEP命令の直後から実行する機能は無い。
先頭にパワーオンリセットとスリープからの起床を判別するコードを書いて分岐する必要がある。

命令

ベースラインからミッドレンジで追加された命令はわずか4つのみである。
ADDLW, SUBLW, RETURN, RETFIE
また、命令一覧から消えた命令が2つある(実はミッドレンジでも使える)。
TRIS, OPTION
その他の命令は、機能は同じだがアドレス指定のビット数が増えている。これによる違いはメモリ構造の項にて。

これらの追加命令の対処法を示す。
・ADDLW
比較的簡単。RAM1つ使用、2命令増で次のようにできる。
    addlw NN
    ↓
    movwf temp
    movlw NN
    addwf temp,W
そもそも加算の順番を変えるだけで済むこともあるだろう。
また、加算が必要かと思いきやIORLWが使える状況もたまにある。

・SUBLW
単純に置き換えようとするとWの退避が面倒なことになる。
    sublw NN
    ↓
    movwf temp
    movlw NN
    movwf temp2
    movf temp,W
    subwf temp2,W
順番を変えて事前に被減数を用意しておくのがよいだろう。つまり、
    movlw NN
    movwf minuend
と準備しておくことにより
    subwf minuend,W
とできる。定数からの減算なら準備は1回でよいためコア部分は同命令数にできる。

・RETURN
ベースラインには値を返さないRETURN命令が無く、RETLWしか無かった。
Wの値を使いたければ、適当な場所に保存しておく必要がある。
    movwf w_buf
    retlw 0
;---
;(呼び出し元)
    call where
    movf w_buf,W
Wを保存しておく必要が無ければ適当な値を返すRETLWをそのまま使えばよい。というより、ベースラインでは「RETURN」が「RETLW 0」のマクロとして登録されているので、何も考えず「RETURN」と書くだけでよい。
なのでむしろ、RETURN命令を使ったミッドレンジ向けコードが書き換えずそのまま動いてしまうことに注意が必要である。

・RETFIE
割り込み機能が無いので当然ながらどうしようもない。

メモリ構造の違い

・RAM(ファイルレジスタ)のマッピング
RAMのバンク分けがミッドレンジ128バイトごとに対しベースライン32バイトごとと、バンクごとの容量が1/4しかなかった。
(対応してファイルレジスタを指定する命令すべてでアドレス指定のbitが7→5と少ない。)
また連続で使えるメモリ量はミッドレンジの80バイトや96バイトに対しベースライン16バイト(bank0は+数バイト)。
ミッドレンジからベースラインへ移行する場合はメモリ量が足りたとしてもバンク切り替えが増えるのに注意が必要である。
ただ、間接アドレッシングで16バイトを超えるメモリを連続的に扱いたいときは、FSRの4bit目を常にセットするように扱えばよいので、ミッドレンジの80バイトと96バイトの領域が混在する複雑な構造よりだいぶ楽である。
またバンク共通のメモリの位置も異なり、ミッドレンジでは各バンクの最後16バイトであるが、ベースラインは前半16バイトのうちSFRでないあまり部分がバンク共通となっている。
図にまとめると以下のようになる。
ベースラインとミッドレンジのRAM構成比較
注:
大抵の機種はこの構成に従っているが、そうでないものもある。おそらく古いものが異なるのだろう。例えば16F84Aはベースラインに似た割り付けである。
図は可能な最大量を示した。実際に実装されているメモリ量がこれより少ない場合、データシートの図はこれと異なる。
ベースラインのバンク共通メモリの量はSFRの量に依存するため、機種により異なる。例えば12F509では9バイト、16F526では3バイトである。

・特殊なレジスタマッピング
特殊なレジスタにTRISxとOPTIONがある。
この2つは、ベースラインでは通常のレジスタとしてマッピングされていない。
その代わりに、「TRIS」命令と「OPTION」命令でWの内容を書き込む仕組みになっている。
書込みのみで読み出しはできないため、あとで値が必要になるなら適当なRAMに保存しておく必要がある。

命令の使い方は、OPTIONはオペランドをとらず、1つしかないOPTIONレジスタにWを書き込む。
    option
ミッドレンジで同等の動作は、(適切なバンクになっている前提で)こうである。
    movwf OPTION_REG

TRISは、オペランドにI/Oポートレジスタ(のアドレス)をとり、対応するTRISxレジスタにWを書き込む。
    tris PORTA
ミッドレンジではこう。
    movwf TRISA

・FlashROM
Flashのページ分けは注意が必要である。
まず、ミッドレンジの2048(0x800)ワード毎に対し、ベースラインでは512(0x200)ワード毎にページが分けられている。
つまり、ミッドレンジでは「0x800の壁」と呼ばれているものはベースラインでは0x200の壁となる。
これに対応してGOTO命令では飛び先のアドレスが9bit指定できるのだが、CALL命令では飛び先のアドレスは8bitしか指定できない。
その分のアドレス1bitを別の場所で指定できるわけでもないため、CALLの飛び先のアドレスは各ページの前半256命令のみで、後半256命令にはCALLで飛ぶことはできない。
ミッドレンジではGOTO・CALLとも同じく11bitになりこの状況は解消されているので、ベースライン特有の制限である。

CALLで飛べるのがページ前半のみということは、後半はサブルーチンに使えないのかというと、そうでもない。
このようにすれば、1命令・2サイクル余計に掛かるものの、サブルーチンの実体を後半に置くことができる。
;(前半)
func1entry:
    goto func1core
;(後半)
func1core:
    ...
    retlw 0
前半に置かなければならないのは、定数テーブル参照などPCL操作をするようなコードのみである。
というわけで、実は印象の割には大した制限ではない。

・バンク・ページ選択
バンクおよびページの選択方法はベースラインからミッドレンジで様変わりしており、注意が必要である。
ROMページ:
ミッド… PCLATHレジスタで指定。
ベース… STATUSレジスタの上位3bitにPA2:0があり、これがミッドレンジのPCLATHと同様の働きをもつ。
RAMバンク:
ミッド… STATUSレジスタの上位3bitにIRP,RP1:0があり、それぞれ間接アドレッシングと直接アドレッシングのバンクを指定する。
ベース… 間接アドレッシングはFSRのみでアドレスを指定できる。直接アドレッシングの場合、FSRの上位3bitと命令からの5bitでアドレスを指定する。

というように、STATUSレジスタの上位3bitの扱いが変わっているので注意が必要である。
またベースラインは間接アドレッシングと直接アドレッシングで別のページを指すことができないことに注意が必要である。

コールスタック

ミッドレンジのコールスタックは8段あり、複雑な事をしなければ足りなくなることはあまり無い。
それに対しベースラインのコールスタックはわずか2段であり、よく考えて使わないとすぐに足りなくなる。

どうしても3段のネストが必要になったら、自力で戻りアドレスを保存してCALL・RETURNを模擬する必要がある。
単純な例を挙げればこんな感じ。
mycall macro where
    movlw $+3
    movwf retAddr
    goto where
    endm
;---
myreturn macro
    movf retAddr
    movwf PCL
    endm
PC上位を保存しておく必要があったり再入可能にするならもっと面倒になるが、そこまで必要になったことが無いので考えていない。

主要レジスタの機能比較

周辺機能の制御用を除いた、コア機能のためのレジスタを比較する。

ベースラインに無いレジスタは、説明済みのPCLATHと、割り込みが無いためINTCONが存在しないのみである。
なお、上で述べたとおり、INTCONが無いということはTMR0のオーバーフローフラグも無いことに注意が必要である。

機能の違うレジスタは3つ。
STATUS, FSR, OPTION(_REG)
FSRについては説明済み。
STATUSとOPTIONを詳しく見る。
なおビット名については、I/OポートがPORTBかGPIOかにより異なる場合がある(例: GPWUF/RBWUF)。ここではGPIOの方を示した。

STATUS
ミッド: IRPRP1RP0/TO/PDZDCC
ベース①: PA2PA1PA0/TO/PDZDCC
ベース②: GPWUFCWUFPA0/TO/PDZDCC
下位5bitは共通。上位3bitが問題となる。
ミッドレンジではおそらくすべての機種で間接・直接のバンク選択に割り当てられている。
ベースラインでは、
①機能の無いもの(例: 16F5x)では3bitすべてページ選択(=PCLATH相当)に割り当てられている。
もっとも、ベースラインのFlash量は最大でも2kワードなのでPA2が使われている機種は無さそうである。
②機能のあるものでは、上位2bitが2種のウェイクアップフラグ(GPIOピン変化・コンパレータ変化)に割り当てられている。
このため両機能のあるものではFlashを2ページ(1024ワード)までしか積めないことになる。

OPTION (レジスタ名はミッドレンジではOPTION_REG)
ミッド: /GPPUINTEDGT0CST0CEPSAPS2PS1PS0
ベース: /GPWU/GPPUT0CST0CEPSAPS2PS1PS0
下位6bitは共通。上位2bitが、
ミッドレンジではポートのプルアップと割り込みエッジ。
ベースラインではピン変化ウェイクアップとポートのプルアップ。
…なんでわざわざポートのプルアップのビットの位置を変えたんだろう。

【余談】

・OPTION_REG
ミッドレンジの「OPTION_REG」レジスタだが、古い機種のデータシートでは「OPTION」レジスタであった。
おそらくOPTION命令との衝突を避けて名前を変えたのだろう。
データシートのリビジョンで記述が変わっていることもあるようだ。
PIC16F87/88 データシート
上: Revision B (August 2003)
下: Revision D (October 2011)
OPTION_REGデータシート比較

・TRIS命令
TRIS命令は命令表にはビットパターンが
0000 0000 0fff
と書かれているがこれは不適切で、PORTA~PORTEまである石では、
0000 0000 0101
0000 0000 0110
0000 0000 0111
0000 0000 1000
0000 0000 1001
がTRISに相当する。

・OPTION2
OPTIONレジスタに加えてOPTION2レジスタをもつ石が存在し(例: PIC16HV504PIC16HV540)、これに書き込むにはTRIS命令を使う
    tris OPTION2
    tris 7
どちらも表に見えていないレジスタに書き込むという実質的に同じ動作なのだろう。
なお、てっきり「tris OPTION2」と書けるものだと勘違いしていたが、OPTION2はincファイルに定義が無く、マジックナンバー「7」で書き込まなければならない。「OPTION2」を「7」と定義しておいてくれれば楽なのにと思いもするが、勘違いで「movwf OPTION2」などと書かせないためだろうか。

・ミッドレンジで隠し命令
TRIS命令とOPTION命令は命令一覧には載っていないもののミッドレンジでも使用可能である。
バンクを切り替えなくともOPTION_REG・TRISレジスタに書き込めるのは便利である。
ただしいくつか制限があり、
・PORTA,B,Cの3つ限定
・Enhancedミッドレンジでは指定する値はPORTA,B,Cとは関係なく5,6,7
・MPLAB8で試した所シミュレータでは不正な命令扱いになってしまった。



編集履歴
2015-08-29

  • 同じカテゴリー(マイコン)の記事画像
    ポケットプリンタ制御
    I2C液晶が動かない理由が分かった
    ゲームボーイの吸い出し機を作った (後編)
    ARMマイコンはじめました。
    SDカードから1セクタ読み取るまでの手順解説
    PICで浮動小数点ウェイトルーチン
    同じカテゴリー(マイコン)の記事
     PIC16のDhrystone MIPSを測ろうとしてみた (2020-04-29 02:23)
     ポケットプリンタ制御 (2018-12-22 17:40)
     I2C液晶が動かない理由が分かった (2017-01-31 01:54)
     ゲームボーイの吸い出し機を作った (後編) (2017-01-16 22:44)
     ARMマイコンはじめました。 (2016-05-28 14:43)
     SDカードから1セクタ読み取るまでの手順解説 (2015-10-05 01:09)
    Post time : 2015年04月11日 23:36│Comments(0)マイコン
    URL欄を実験的に消してる間に廃止されてしまいました。まあいいか。
     
    <ご注意>
    書き込まれた内容は公開され、ブログの持ち主だけが削除できます。
    削除
    ベースラインPICの注意点
      コメント(0)