2013-02

2012-09 FM3 RX62N SH2A PIC32MX


2月

持ち越し案件

  • pic32mxでFTDI互換(JTAG)ファーム
    いまさらpic32mx220デバイスを使ってみようと思う。





PIC32MXについて




AndroVMというAndroidエミュレータ on Windows

AndroVM.org


  • androVM_vbox86tp_4.1.1_r4-20121119-gapps-houdini-flash.ova という仮想マシンを入手してみる。

実行前にすることとしては、

  • VirtualBoxから、androVM_vbox86tp_4.1.1_r4-20121119-gapps-houdini-flash.ovaという仮想マシンをインポートする。
  • 仮想マシンに与えるVRAMを128MBにする。
  • 仮想マシンに与えるネットワークを「無効」から「ホストオンリー」に変更する。

そして、仮想マシンを起動する。

  • 普通にGooglePlayが使えるけど、これっていいのか?




pic32progに関する私見

  • プログラムソースの規模は比較的小さい。
    • 以下の4種類のドライバーが存在する。
      ソースファイル説明下位層
      adapter-mpsseFTDI FT2232用のMPSSEによるJTAG層ドライバーlibusb
      adapter-pickit2Pickit2用のICSP(PGD、PGC)ドライバーhidapi(実装はlibusb(Linux)もしくはWin32API直叩き)
      adapter-hidbootMicrochip HID bootloader(古い)用の書き込みhidapi
      adapter-an1388Microchip USB bootloader(Application Note 1388で公開されている)用の書き込みhidapi

特徴としては、

  • Windows/LinuxでHIDデバイスを叩くサンプルとしてとても参考になる。
  • Windows/Linuxで(libusb-win32経由で)FT2232Dを叩くサンプルとしてとても参考になる。


そして、自家製ドライバーの追加は比較的簡単なので、自分でドライバーを追加できる。


だが、困ったこともある。

  • I/O Portを直接上げ下げしてPGC,PGDを操作している部分のソースがないこと。
  • bootloader経由やPICkit2経由のものは、結局firmwareのソースまで調べないと分からない。
  • mpsseのソースが唯一Port操作を行なっているけれど、mpsse経由なので読みづらいこと。
  • それから、mpsseのソースはJTAG操作なので、ICSPの操作の参考になりにくい。




pic32prog始動!

やっと動いた。

  • Pickit2のファームウェアをPIC18F2550に焼いて、なんちゃってPickit2をでっち上げる。
  • pic32progを再ビルドして、PIC32MX220のfuse読み出しに成功。


  • Pingunoのフレームワークとコンパイラを使ってLチカも出来ました。
  • サンプルソースでは、ブートローダー用のHEXとスタンドアロン用のHEXの両方を生成します。





PIC32MX220F032Bは難易度高め。素人には到底お勧めできない。

いろいろやってみてわかった。

なぜか

  • (1)後閑さんの分かりやすい書籍とか資料がない。
  • (2)エラッタが多い。
  • (3)32kBのFlashは狭すぎる。
  • (4)Arduinoっぽい、素人向けお手軽環境Pinguinoはまだまだ全然こなれてない。
  • (5)まれにPICスレにいらっしゃるアセンブラオンリーな人にとっても、遅延スロットとか遅延ロードとか
    .set noreorder
    ...
    .set reorder
    とかで書くのがとてもいたたまれない。

(なんとMIPSアセンブラは命令を勝手に並べ替えてしまうので、それやられたらバグる部分だけ上記のような擬似命令で囲うという風習があるけれど、これよっぽどMIPS慣れしてる人じゃないと投げ出しますな。)

  • (6)MPLABX+XC32でも、そんなに楽じゃない(気がする)。


  • とはいえ、PinguinoはほぼArduinoと同じように使えるので、Flash128kBのチップが安く入手できるようになるとか、OlimexのPIC32基板を入手できるならそんなに悪くないと思っている。
  • Pinguinoのスケッチがおおむねちゃんと動くようになってればね。
  • 今はまだ無理。OnTimer()とか割り込みとかSerialとか、ちゃんと動かないし。


そういうわけで・・・

まとめ

  • Pinguinoの環境は、フリーなmips-gccコンパイラとして使う程度に考える。
    • 自力でクロスgccをビルドするよりずっと楽。
    • 一応Pinguinoブートローダーからスケッチ動かしてCDCprintf()出来るので、USB-CDCのフレームワークとしても使えなくはないレベル。
    • スタンドアローンでCDCprintf()がまだ成功していない。
    • Pinguinoのスケッチはメモリーマップの関係で16kBまでしか焼けないけれど、ブートローダーをなんとかすればもう一声いけそう。そうすれば実行できるスケッチはだいぶ増えるのに。
  • ブートローダーのソースが入手出来てない。
    • UBW32プロジェクトのHIDbootX.zipをDLしてみたけれどMPLABX上でのビルドがうまく出来ない。そもそもMX220対応してない感じ。
    • MchipのAN1388はソースがあるけれど、これもMX220でうまくビルドできないとか、ビルドはしても動かない感じがする。(挑戦中)
  • MPLABX+XC32はGUIがわかりにくくてしんどい。





PIC32MX220F032B: Pinguinoで、CDCprintfと割り込みとLチカ同時技のスケッチを書いてみる。

だいぶコツが掴めてきた

  • これ。
    // Using interrupt with Pinguino32
    // Jean-Pierre MANDON 2011
    
    #include <interrupt.c>
    
    unsigned int counter=0;
    
    
    void ISR_wrapper_vector_4(void) __attribute__ ((section (".vector_4")));
    // Put the ISR_wrapper in the good place
    
    void ISR_wrapper_vector_4(void)
    {
    	Tmr1Interrupt();
    }
    // ISR_wrapper will call the Tmr1Interrupt()
    
    void Tmr1Interrupt(void) __attribute__ ((interrupt));
    // Tmr1Interrupt is declared as an interrupt routine
    
    // define here the code to execute when an interrupt occure
    void Tmr1Interrupt(void)
    {
    	if (IFS0bits.T1IF) {	// Timer Interrupt flag
    		TMR1=0;			// reset the timer register
    		IFS0CLR=0x10;		// Clear the timer interrupt flag
    		counter++;		// increment the counter
    	}
    }
    
    // configure timer 1
    void init_timer1(void)
    {
    	IntConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);	// interrupt mode (interrupt.c)
    	T1CON=0;		// reset timer 1 configuration
    	TMR1=0;			// reset timer 1 counter register
    	PR1=0x9999;		// define the preload register
    	IPC1SET=0x7;		// select interrupt priority and sub-priority
    	IFS0CLR=0x10;		// clear interrupt flag
    	IEC0SET=0x10;		// enable timer 1 interrupt
    	T1CONSET=0x8010;	// start timer 1 and set prescaler
    }
    
    void setup()
    {
    	pinmode(13, OUTPUT);
    	init_timer1();
    }
    
    void loop()
    {
      static int cnt=0;
      cnt++;
      if(cnt >= 500) {
            CDC.printf("%d\n\r",counter);	// counter is incremented at each timer 1 overflow
            toggle(13);
            cnt=0;
      }    
    	delay(1);
    }

さて、このスケッチのどこが暗黒面かを説明しよう。

まず、PICのUSBエンジンは(PIC18Fのころからだが)割り込みを使わなくてもポーリングだけで動くという素敵なメリットがある反面、

  • ポーリングモードで使用する場合は必ず1mS以内に1回はポーリングしてやらないと、不明なデバイスになってUSB接続が切れるのだ。
  • で、このスケッチでどうやってUSBポーリングしているかの種明かしをしよう。
int main() {
        ・・・
	setup();

	while (1)
	{
		#ifdef __USBCDC
			#ifdef __32MX220F032D__
				USB_Service( );
			#else
				CDCTxService();
			#endif
		#endif
 
		loop();
	}
  • と、まあこういうことなのだ。分かったかな?
  • USBを使いたければ、スケッチに記述するloop()関数は1mS以内に応答を返す必要がある。それが出来ないなら、割り込みを使うか、loop()内のユーザーループでも常にUSB_Service()を呼び出すように心がける。



これをBOOTLOADERから起動ではなくて、pic32progで直書きして動かすコツも同時に会得した。

  • それは、割り込みベクターを別のアドレスベースに設定するマクロを使って、デフォルトアドレスに戻せばいいのだ。
  • こんなやつ。
    	_CP0_SET_EBASE(0xBD003000); // Set an EBase value of 0xBD003000 Pinguinoから起動。	
    ---
    	_CP0_SET_EBASE(0xBFC00000); // Set an EBase value of 0xBFC00000	ライター書き込みの単独HEX
  • 但し、IntConfigureSystem()内に_CP0_SET_EBASE()が記述されているので、その直後にやるとかしないとだめなのだ。
  • さらに言うと、IntConfigureSystem()はTimer割り込みがバリバリ来てる時にやっちゃあいけない。
  • 割り込み発生前にIntConfigureSystem()やって、直後に_CP0_SET_EBASE()で正しいベクターを設定する。タイマーの設定はその後だ。
    // configure timer 1
    void init_timer1(void)
    {
    	IntConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);	// interrupt mode (interrupt.c)
  • リンカスクリプトの差し替えやConfig Fuseの追加も必要だ。






PIC32MXはこの先生きのこれるのか?

これまでのまとめ。

  • PIC32MXライター: PIC18F2550使用の簡易型PicKit2互換機はとても安定して動いている。満足
  • ライターソフト:pic32progも少しの改造により実用品になっている。


  • コンパイラ、フレームワーク:
    • (1)Pinguino: mips-gccとPinguino環境、ライブラリ、ヘッダーがある。スケッチはまだ一部しか使えない。ブートローダーはそのまま動く。ユーザーエリアが僅か16Kしかないけれど、ブートローダーを使わずにスケッチを自己起動形式でビルドできるようになったのでそっちだと32K使える。
  • (2)MPLAB: Mchip提供のpic32-gccとヘッダー、ライブラリ、USBサンプルがある。
  • 上記2つはあまり互換性がない。ソースの行き来がやりにくい状態。


  • ブートローダー
    • (1)AN1388: MPLABでビルドできる。-mips16化もOK。安定している。Pinguinoのローダーと互換性がない。
    • (2)UBW32用のHIDBoot.X.zip : MPLABでビルドできる。-mips16化もOK。安定化してみた。問題は、HEXが全く焼けないこと(原因究明中)。Pinguinoのローダーはおそらくこれがベースなんだけど、MX220対応済みソースが入手できない。
    • (3)すzさんのhidboot: ビルドできて、ループを回しながらLED点滅まで動いているけれど、USBデバイスになってない。作りかけ(?)
    • つまり、ブートローダーはとりあえずPinguino付属のHEXは動くけれど、ソースがない状態。

この先生き残れるか?

  • (PLAN A)とりあえず、焼けないローダーを改造しつつ、pix32spxのようなもの(簡易モニタ)を書く。
  • (PLAN B)焼けないローダーを焼けるようにする。


あるいは、

  • (PLAN C)Pinguinoのcdcライブラリを使ってcdctoolを動かせるようにする。


得失

  • 前者はMPLAB依存してしまうので60日で切れる。
  • 後者はCDC以外のデバイスになれない(要検証)のと、cdcライブラリのソースが相変わらず無いことが問題。


そうすると最後の手段としては、MCHIPからヘッダーだけ抜き出して、Pinguino gccでビルドできるような環境を 作るしかないのか。

面倒すぎる

面倒すぎるけれど、そうすることで、crt0.Sを改造したものを差し替え出来るようになるので、ローダーのサイズを8kB以内に収めるというのも夢ではなくなるかも。

MPLABのリンカーオプションをいくら弄っても(-nostartfiles)、crt0.Sの差し替えが出来なかった。


結論: PLAN Aを進めてみるつもり。





しつこくPIC32MX続き。

HIDBoot.Xのバキバキ改造は一区切り付いた。

  • FLASHが書き込めない原因は、NVMWriteWord()の前のEraseでエラーしてリカバリーできていなかった模様。
  • AN1388のNVMem.cを借用してきた。他にもEraseのループ回数は間違ってた模様。
  • PAGE SIZEが4096決めうちになっていたけれど、MX220では1024に変更しないといけない。

ついでに、-mips16化して、コードサイズを最小に追い込んだら、8K(+3K)のサイズに収まった。

  • 一応動いている。PLAN B終了。 これでユーザーエリアは24kB確保できた。

<前の月次の月>