2013年04月02日

PIC32: MPLAB(X)でmips16オプションを使うときのメモ 2013

PIC32: MPLAB(X)でmips16オプションを使うときのメモ 2013

* はじまり
* C32とXC32
* mips16オプションの指定方法
* 注意点
* C32コンパイラ
* XC32コンパイラ
* 非常に重要なコード削減オプション "--gc-sections"
* MPLABX上で複数のコンパイラバージョンを切り換えるときの注意点
* MPLABX(v1.70以降)のMakefile + C32 + mips16 でコマンドライン・コンパイル
* 60日のお試し期間かどうかを確認する方法
* -Osオプションの効果 (^^)/

* 効果は絶大だった!!
* PIC32MX250F128Bを使う Flash=128KB, SRAM=20KByte
* C32に未来はない!

* はじまり
PIC32: MPLAB(X)でmips16オプションを使うときのメモ。

ここでは無料で使えるLite版のコンパイラC32、XC32に限って記述する。
mips16オプションはPIC32のコードサイズを劇的に減少させるコンパイラ・オプションであり、(注1)(注7)
220円ポッキリの少FLASH版PICMX220F032Bでは必須となる。
しかし、
Microchipは無料版コンパイラに対してmips16オプションを無効にする方針だ。
ちなみに、mips16オプションは「別に最適化オプションじゃなくて」、
MIPSコア(MIPS32 M4Kコア)が持つ基本機能の使用を選択するオプションなのだ。

以下、ここで使った現時点(2013/04)の最新版を
MPLAB v8.90
MPLABX v1.70
C32 v2.02a
XC32 v1.20
とする。
C32とXC32はインストール時に最初から「Lite版」を選択しています。
従って、60日の試用期間は「最初から終了した状態」で使います。(注8)

* C32とXC32
PIC32用のCコンパイラは、「C32」と「XC32」の2種類がある。
双方ともMPLAB、MPLABX上から使用することが可能。
(MPLABでXC32、MPLABXでC32を使うことも可能)
さらに複数バージョンのコンパイラをインストールすれば、IDE上で切り換えて使用できる。

C32は基本的にMPLABに付属しているが、古い版は以下のページから取得出来る。
過去のMPLAB(X)、コンパイラ倉庫:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023073

* mips16オプションの指定方法
基本的に以下の使い方がある。
(a) コンパイル時、「-mips16」オプションを追加する。
    但し、この機能はC32、XC32共に無効になっています。
(b) 関数に __attribute__ ( (mips16) ) オプションを追加する。
    C32は効果有りで、XC32は効果なしです。
(c) #pragma GCC option("mips16") をソースコードの先頭に追加する。(注3)
    この機能はC32、XC32共に無効になっています。
(d) リンク時にリンカに「-mips16」オプションを追加する。
    C32は有効、
    XC32は原則無効で、バグで有効になります。(爆
    リンク時に「-mips16」を指定すると、リンクされる標準ライブラリやペリフェラル・ライブラリが
    「mips16バージョン」になるので状況によっては大きくFLASH容量を削減できます。

以下、上記のオプションを個別に「mips16オプション(a)」の様に表記する。
まとめ:
(1) 効果があるのは基本的に「C32でmips16オプション(b)と(d)」です。
(2) 従って、ソースコード上のmips16化したい全ての関数に、
 __attribute__ ( (mips16) ) 
  を付加する必要があります。
  手間といえば手間ですが、その気になれば、なんとかなる。(爆
以下を使います。
"mips16.h":
#ifndef __MIPS16_H__
#define __MIPS16_H__

#define _MIPS16 __attribute__ ( (mips16) )

#endif    /* __MIPS16_H__ */ 
これを、mips16化したいソースコードの先頭に付加します。 例えば、
#include "mips16.h"
...

void foo( void ) {
  ...
  }
uint32_t *bar( void ){
...
}
を
void _MIPS16 foo( void ){
  ...
  }
_MIPS16 uint32_t *bar( void ){
  ...
  }
に変更。
ソースコードが多数あっても、置換していくだけなので1時間もあればケリが付く話(オントカヨ (爆 努力に見合った結果が得られることは間違いないだろう。(体験済み) (爆 また、全部一度にやる必要もなくて、ひとまずサイズの大きな関数やファイルだけを重点的に、 _MIPS16化して行けば良いと思います。 * 注意点 以下の話では、最適化コード・オプションを「-Os」にして、「-mips16」を付加しています。 無料版コンパイラの場合、双方共に一部を除いて無視される方向ですが、(詳細は後述) ここでは「無視するなら勝手に無視してくれ」というスタンスをとる事にします。(注5) * C32コンパイラ C32でmips16オプション(b)が有効になるバージョンは「C32 v2.00以降」です。 v1.xx系はmips16非対応な上、古いので使わない様にします。 C32はMPLABに付属しているのでMPLABを最新にするか、 上記の倉庫から最新のC32(今ならv2.02a)を取得して使った方が良いです。 * XC32コンパイラ 以下はXC32 v1.20の場合です。 全面的にmips16オプションが無効にされている。ただし、"リンク時のみ"「-mips16」オプションがバグ?で有効になる 現象がある。従って将来遮断される可能性が高い。 * 非常に重要なコード削減オプション "--gc-sections" Maple(ARM STM32)やArduino(AVR)のgccでは普通に有効になっている重要な「コード削減オプション」である。 「-mips16」オプションもここで指定しておく。 設定方法: MPLAB、MPLABX及び、C32,XC32共通。 コンパイル・オプション設定ダイアログで以下のチェックを有効にする。 コンパイラ: 「Compiler」- Categories:「General」画面で、 "Isolate each function in a section" "Place data into its own section" "Generate 16-bit code" これは一応、コンパイラの挙動に関わらずチェックしておくことにする。 「Compiler」- Categories:「Optimization」画面で、 「Optimize Level」の図で、「s」(= -Os)にします。(これも無視されます) 少なくとも「-O0」以外にしておくべきです。 リンカ: 「Linker」- Categories:「General」画面で、 "Remove unused sections" にチェックを入れる。 「Linker」- Categories:「Libraries」画面で、 "Optimization level of Standard Libraries" を「s」 ( =-Os) "Genarate 16-bit code"にチェック 項目の表現はMPLABとMPLABXで微妙に違いますが、大体分ると思います。 上記設定でコンパイル時に、 -ffunction-sections -fdata-sections -mips16 リンク時に --gc-sections -mips16 が追加されることになる。 (MPLABX上ではリンカの-mips16指定は出来ない) * MPLABX上で複数のコンパイラバージョンを切り換えるときの注意点 MPLABX v1.70の場合である。 例えばC32の場合、デフォルトで「半角スペースを含む」フォルダにインストールされる。 このあとC32の別バージョンをインストールしても認識はされるが、切り替えできない状態に陥る。 この場合、全てのC32コンパイラを「半角スペースを含まない」フォルダにインストールし直すことで解決出来る。 * MPLABX(v1.70以降)のMakefile + C32 + mips16 でコマンドライン・コンパイル MPLABXのv1.70から、MS-DOS窓で使える「Makefile」が生成されるようになった。 プロジェクトのトップフォルダで「make」コマンドを打てばコマンドライン・コンパイルが出来る。 ただし、「make.exe」はMPLABXに付属のものである必要がある。 例えば、 D:\MPLABX\gnuBins\GnuWin32\bin\make.exe を使う必要がある。 以下のバッチファイル群を使えば、このMakefileを使って「C32 + mips16」でコンパイル出来てしまいます。 (_MIPS16化は必要) MPLABX上の「mips16」オプションの有効、無効にかかわらず、「-mips16」オプション付でコンパイルします。 従って、MPLABX上で作った新規プロジェクト(C32用)にも効果があります。 m.bat mm.bat asm-list.bat 準備中 * 60日のお試し期間かどうかを確認する方法 コンパイル・オプション設定ダイアログで以下のチェックを有効にする。 「Compiler」-「Optimization」画面で、 「Optimize Level」の図で、「s」(= -Os)にします。 この状態でコンパイルすると、お試し期間切れ(無料のLite版状態)なら以下の様なメッセージがOutputウインドウに表示されます。 ... warning: Compiler option (Optimize for size) ignored due to an invalid license ... warning: Disable the option or visit http://www.microchip.com/c32 to purchase a full standard-edition license. * -Osオプションの効果 (^^)/ C32コンパイラに於いて、コード最適化オプションは以下の状況を示す。 -O0(オーゼロ): 最適化一切なし。コードは冗長。 -O1,-O2,-O3,-Os: 一定の最適化が有効になる。この中のどれを指定しても同じ。(注11) コードサイズは激減する。 従って、このページでは代表値として「-Os」を使用する。 コードサイズが激減する現象は以下のページと同じと思われる。 PIC24F:「C30のLite版の最適化オプション」 Microchipが禁止しているのは、多数の最適化項目の内、 最適化レベル(1,2,3)に依存する項目と、「コードサイズ」に関する部分のみと推測できる。(注9) 従って、それ以外の多くの最適化項目が有効になっていると思われる。 * 効果は絶大だった!! このページに書いた設定を全部適用すると、どれくらいの効果があるか確認してみました。 比較は「プロジェクトのデフォルト設定のまま」と「このページの設定適用後」(_MIPS16化含む)です。 コンパイラはC32(v2.02a)です。内容はMicrochipの「FatFSデモプロジェクト」です。 順番にオプションを追加していき、個々のFLASH削減量を見ていきます。 (1) プロジェクトのデフォルト設定のまま:(最適化一切なし) 53.1KByte PICMX220F032BだとFlash容量オーバーで使えません。 (2) 上に--gc-sections系を追加してみる: 43.1KByte 10KByteも減ります。(^^)/ (3) さらに「-Os」オプションを有効にしてみる: 28.5KByte 実は15KByteも減るのね。 (^^)/ (4) さらに-mips16オプションと「_MIPS16化」を追加する: 18.8KByte さらに10KByte減りました (^^)/ 53.1KByte が最終的に 18.8KByte まで縮みました。スゴすぎ!! この様に絶大な効果が得られます。 PICMX220F032Bだと全然無理と思われたプロジェクトも余裕で使えることになりました。(注10) おしまいっ!! (オイ * PIC32MX250F128Bを使う Flash=128KB, SRAM=20KByte PIC32MX250F128B 483円 http://jp.rs-online.com/web/p/microcontrollers/7680836/ というわけで、いろいろ気にしたくない場合、上記のマイコンを使えばスッキリします。 最終的にFlash=32KByte SRAM=8KByteで収まるならPICMX220F032Bにダウングレードするという 方が楽ちんですね。 * C32に未来はない! 現在、MicrochipはC32に変えてXC32コンパイラを推奨している。 C32のフォルダを探索してみると、v2.02aの最も新しいファイルの最終変更日付が2011/11/28である。 もう1年以上も放置されていることになる。 残念ながらC32は既に捨てられたと考えるの妥当だ。 従って、C32をメインで使用するなら、最新のXC32で提供されているヘッダファイルやペリフェラルライブラリのソースコード とC32内のそれらと比較チェックが必要だろう。 参考ページ: irukaさんのページ PIC32MX http://hp.vector.co.jp/authors/VA000177/html/PIC32MX.html (注1) ARM7のThumbコードのイメージ。 (注2) 使用の可否はGCCマニュアル参照 (注3) この機能は、一般的なGCCなら使える可能性があって、 ソースコード内(任意の場所から、〜までとか)でコンパイル・オプションを変更可能なので、 ある状況下では非常に便利です。(括弧内に任意のコンパイルオプションを指定出来る。)(注2) (注5) コンパイル時の警告がうっとうしい場合は変更しても良いかもしれませんが、最適化が効かなくなります。 (注6) IDEの再起動、又はコンパイラ・オプション画面を出して「Apply」が必要。 (注7) 注意ポイントとして、mips16化コードは実行速度が30%程度低下する。 (注8) 60日試用期間を有効にしてもかまいませんが、ここでは60日経っても状況が変わらないように 配慮しています。60日後に「そんな話聞いてないっ!!」とならない様に。(オイ (注9) 一般的な最適化グループ項目の詳細はGCCのマニュアルにある。 (注10) 動くかどうか試してないけど、普通は大丈夫だと思います。(^^; (注11) 実はビミョ〜に変化する場合もありますが、微妙なので無視します。
posted by Copyright (C) audin All Rights Reserved. at 00:00| Comment(4) | PIC32MX | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
audinさんこんばんは。

>でもC32の-Osと-mips16使用可能の60日制限は残るような気がしますね。

勘違いでした。はっ、恥ずかしい。

自分は60日版をインストールしてしまったので、
60日たったら使えなくなる強迫観念が残っていて、
それを回避するためにPinguino-gccでビルドする方策
を取ったのでした。



>一応、PIC32の利用者が増えて情報も増えたらいいなぁ、というのが趣旨だったりします。

御意です。


秋月220円のこの石はコスパが良すぎるので広めるべきであります。

例えばArduinoでUSB HOSTを組もうとするとHOST Shieldが要りますから結構高くつきますし、基板
が2階建てになりますけど、MX220だと220円です。おまけに速度性能も10倍くらいありますのでウハウハです。ただ、以下の如く難易度高めなのが玉に疵です。

1)エラッタが多い。
2)Mchipの各サンプルソースをMX220用に改造するのに少しだけスキルが要る。
3)私みたいに純正キット・ライター買わない人にとって最初のLチカに成功するまでが冬山登山くらい難しいです。(w
Posted by iruka at 2013年04月04日 19:59
こんばんわ audinです
>でもC32の-Osと-mips16使用可能の60日制限は残るような気がしますね。
最初からLite版を選択してインストールしていますがC32のatrributeオプションは問題なく使えています。

Makeとmips-gccでゴリゴリ書ける人はそんなに多くないだろうと思います。今のところPinguinoも情報がirukaさんのところだけですし。(^^;
(自分的には非常に参考になっていますが)
MPLAB(X)から使えればPIC32の利用者も少しは増えるんじゃないかなぁと思っています。

>C32からPinguino-gccへのお引越しは可能です。
Microchipのペリフェラルライブラリを多数使っているとちょっと手間かもしれません。
個人の力量とやる気依存でしょうか(^^;

>もしPIC32MX250F128Bが秋月扱いになれば
RSコンポーネンツでも確か450円くらいなので
それを買ってしまても良いと思っています。
かなり気が楽になると思います。(^^;

>そいつらだけMIPS32コードにしておけば、速度低下の問題は緩和されると思います。
全くその通りだと思います。

一応、PIC32の利用者が増えて情報も増えたらいいなぁ、というのが趣旨だったりします。
Posted by audin at 2013年04月04日 00:20
続きです。

もしPIC32MX250F128Bが秋月扱いになれば
別に-Osと-mips16が無くたって、ヘッチャラです。 -O0どんと来いです。コードサイズが4倍になってもチャラです。

それから速度支配的な関数というのは(自分で書いてる限り)どれが遅いか分かると思いますので、
そいつらだけMIPS32コードにしておけば、速度低下の問題は緩和されると思います。
Posted by iruka at 2013年04月03日 19:03
こんばんは。

なるほど、やろうと思えばMPLABX+C32という組み合わせも可能なんですね。
でもC32の-Osと-mips16使用可能の60日制限は残るような気がしますね。


私は基本的にPinguino付属のmips-gccを使うことに決めました。

#pragmaが使えないのと割り込みルーチンの__attribute__ が微妙に異なる件を除けば、
C32からPinguino-gccへのお引越しは可能です。

(IDEは使いません(使えません)がMakeのほうが好きなので問題ありません)
Posted by iruka at 2013年04月03日 18:53
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。