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 コンパイラー)では、次のようにコンパイルされる。
1サイクルですむ。最速で16 Mhzだから、63ナノ秒である。
同じことを、C32でやってみると(最適化はレベル1)
7サイクルもかかる。PIC32MX150F128Bだと最速で40 Mhzだから、175ナノ秒かかる計算。PIC32MXシリーズの最速である80 Mhzでも、88ナノ秒であり、PIC18Fよりも遅い。
同じ動作をするほかの命令を試してみた。
どうやら、「LATB^0x0001」が一番速いようで、80 Mhzの石では50ナノ秒、40 Mhzの石でも100ナノ秒だから、PIC18Fと比較して、同程度のスピードで実行できる。
このままでは使い勝手が悪いので、次のようにしてみた。
これなら、使い勝手はよいだろう。さらに、
とすれば、ビットのセットとクリアーも、同じように4サイクルで実行できる。
C32もだんだん分かってきたので、何か作ってみよう。ただこの感じだと、必ずしも大は小をかねるということにはならなさそうである。ケースによっては、むしろPIC18の方が速いというようなことが、多々ありそう。PIC18に搭載のCPUは、さすが組み込み用にチューンアップされたものと言える。
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;
1のbit"のみ"を、それぞれセット,クリア,反転できるようです
ビット反転は下記の方が1命令短いようです
LATBINV = 0x0001;
Katsumi (2012年5月16日 09:23:12)
zxcさん
どうも有り難うございます。新しく扱うものなので、コンパイラのみに頼ってました。Datasheetをちゃんと見た方が良いですね。
後で気がついたのですが、読み込み用の "lw" は2クロック使います。LATBINVの使用で "lw" も使わなくて済むのなら、さらに早くなりそうです。
割り込み等、少しでも早いレスポンスが求められる時など、こういった情報は本当に有り難いです。
どうも有り難うございます。新しく扱うものなので、コンパイラのみに頼ってました。Datasheetをちゃんと見た方が良いですね。
後で気がついたのですが、読み込み用の "lw" は2クロック使います。LATBINVの使用で "lw" も使わなくて済むのなら、さらに早くなりそうです。
割り込み等、少しでも早いレスポンスが求められる時など、こういった情報は本当に有り難いです。