PIC

MPLAB C32 compilerを使ってみた

2012年4月27日

Microchip のPIC32シリーズに、PIC32MX150F128B / PIC32MX250F128B という、DIP-28 の石を見つけた。RAM も 32 KB あるし、PIC32MX250F128B の方は USB ホストとしても使えるので、色々と面白いことに使えそう。価格も、$5 前後と、手ごろである。早速注文したので、2-3日で届くはずだが、待ちきれず、MPLAB C32(PIC32 用の C コンパイラー)で少し遊んでみた。

PIC32は、Microchip独自の開発のCPUではなく、MIPS (Microprocessor without Interlocked Pipeline Stages)という、MIPS Technologiesが開発している RISC アーキテクチャの CPU を用いている。どうやら、ARM に似ているらしい。

レジスタは、32 bit 幅だから、長サイズの整数や浮動小数点演算などは、得意なはずだ。他方、組み込みマイコンではI/Oなどとの連絡を行う必要がある。そちらはどうかと、色々調べてみた。

ポートBのビット0を反転させる動作を考えてみる。これは、「LATBbits.LATB0=!LATBbits.LATB0」という命令で書けるのだが、MPLAB C18 (PIC18F用の C コンパイラー)では、次のようにコンパイルされる。

LATBbits.LATB0=!LATBbits.LATB0;
  000E    708A     BTG 0xf8a, 0, ACCESS

1サイクルですむ。最速で16 Mhzだから、63ナノ秒である。

同じことを、C32でやってみると(最適化はレベル1)

LATBbits.LATB0=!LATBbits.LATB0;
9D0000D8  3C02BF88   lui         v0,0xbf88
9D0000DC  8C446130   lw          a0,24880(v0)
9D0000E0  30840001   andi        a0,a0,0x1
9D0000E4  2C840001   sltiu       a0,a0,1
9D0000E8  8C436130   lw          v1,24880(v0)
9D0000EC  7C830004   ins         v1,a0,0,1
9D0000F0  AC436130   sw          v1,24880(v0)

7サイクルもかかる。PIC32MX150F128Bだと最速で40 Mhzだから、175ナノ秒かかる計算。PIC32MXシリーズの最速である80 Mhzでも、88ナノ秒であり、PIC18Fよりも遅い。

同じ動作をするほかの命令を試してみた。

LATBbits.LATB0=~LATBbits.LATB0;
9D0000D8  3C02BF88   lui         v0,0xbf88
9D0000DC  8C446130   lw          a0,24880(v0)
9D0000E0  00042027   nor         a0,zero,a0
9D0000E4  8C436130   lw          v1,24880(v0)
9D0000E8  7C830004   ins         v1,a0,0,1
9D0000EC  AC436130   sw          v1,24880(v0)

LATB^=0x0001;
9D0000D8  3C02BF88   lui         v0,0xbf88
9D0000DC  8C436130   lw          v1,24880(v0)
9D0000E0  38630001   xori        v1,v1,0x1
9D0000E4  AC436130   sw          v1,24880(v0)

どうやら、「LATB^0x0001」が一番速いようで、80 Mhzの石では50ナノ秒、40 Mhzの石でも100ナノ秒だから、PIC18Fと比較して、同程度のスピードで実行できる。

このままでは使い勝手が悪いので、次のようにしてみた。

#define toggle(x,y) x^=1<<y
toggle(LATB,15);
9D0000D8  3C02BF88   lui         v0,0xbf88
9D0000DC  8C436130   lw          v1,24880(v0)
9D0000E0  38638000   xori        v1,v1,0x8000
9D0000E4  AC436130   sw          v1,24880(v0)

これなら、使い勝手はよいだろう。さらに、

#define set(x,y) x|=1<<y
#define clear(x,y) x&=(~(1<<y))&0xFFFF

とすれば、ビットのセットとクリアーも、同じように4サイクルで実行できる。

C32もだんだん分かってきたので、何か作ってみよう。ただこの感じだと、必ずしも大は小をかねるということにはならなさそうである。ケースによっては、むしろPIC18の方が速いというようなことが、多々ありそう。PIC18に搭載のCPUは、さすが組み込み用にチューンアップされたものと言える。

コメント

zxc (2012年5月16日 03:57:45)

Datasheetにビット操作用に LATxSET , LATxCLR , LATxINVの記載があり
1のbit"のみ"を、それぞれセット,クリア,反転できるようです
ビット反転は下記の方が1命令短いようです
LATBINV = 0x0001;

Katsumi (2012年5月16日 09:23:12)

zxcさん

どうも有り難うございます。新しく扱うものなので、コンパイラのみに頼ってました。Datasheetをちゃんと見た方が良いですね。

後で気がついたのですが、読み込み用の "lw" は2クロック使います。LATBINVの使用で "lw" も使わなくて済むのなら、さらに早くなりそうです。

割り込み等、少しでも早いレスポンスが求められる時など、こういった情報は本当に有り難いです。

コメント送信