LPC4330を使ってみる2 -OpenOCDでSPIFI-SPIROMに書き込む-

先日秋月さんからもLPC4330-XplorerLPC1830-Xplorerが販売されたわけですが、
ななんとデバッガハードウエアのULINK-MEもついて6200円ですって!本体+DHLの
送料合わせて1万ちかく払って半分壊れたのよこされた私はなんだったのか!?あと
たった2週間ちょっとまてばULINK-MEゲッツ出来たじゃないか!と悔やんでも仕方が
ないのでホビイストとしては手元にあるものを100%活用していこうと思います。
特に大将からご指名受けてしまい放り投げることもできないのですがFatFs実装は
あつをさんおねがいいたします(パタ


さて、LPC4330-Xplorer上ではSPIFIというインターフェースでマルチチャネル
I/O対応のSPI-ROMとLPC4330とが繋がっています。
LPC4330は起動オプションによりこのSPIFI-SPIROMから直接起動&プログラム
実行&リニアな参照ができるというなかなかニクい機能があるわけですが、
内蔵フラッシュを持たないLPC43xx・LPC18xxはどうにかしてこいつにプロ
グラムを書き込まなければなりません。有効と思われる方法は以下の2通り。
1.付属のULINK-MEを繋げてKEILのIDEを使ってプログラムをSPIROMに書き込む。
 ↑ULINK-MEもってないので却下。
2.DFUブートローダー経由でSPIFI-SPIROMに書き込む
 ↑情報が出そろってませんがいずれ試します…。
  RAM上には流せられるのは確認しました。


OpenOCDは実はSPIFI-SPIROMの書き込みにすでに対応していましたもちろん公式
にはコミットはされていないので自分でパッチ当て+再ビルド必須ですが、私の試行した
限りではいい結果を得られたので上述の確実な2通りに"もう一つ"追加したいと思います。

20120927追:
公式のコミットにも上がりました!


今回はこのOpenOCDを使った方法をご紹介します。


●その前にGCCでコマンドラインビルド可能なLチカるプログラムをこさえる
前回の時点ですでにOpenOCDにつなげて最初に書き込まれていたSPIROMの内容
のバックアップは取っていましたが自分でこさえたのをやっぱり書き込みたいよねと
いうことでいつもののLPC4330版を見据えたベース作りを行います。

LPC4330のSRAM+SPIFIの構成は以下の図のようになっています。

LPC4330コアの最大周波数204MHzでアクセスできるLocalSRAMは合計で200kByte
ありますがご覧のとおりアドレスは連続になってはおらず、128kByte・72kByte分で
ぶつ切りとされています(AHBRAMは構成的に64kByte分すべて連続アクセス可能です)。

SPIFIから実行した場合,104(MHz)/2(Byte)の読み取り速度のボトルネックがあります
ので見かけの動作速度は超大雑把に見積もって30MHz以下になっちゃいますが、ひと
まず一番単純な構成でプログラムも組み易いEXECUTE FROM SPIFIなメモリプラン
を構成しLチカプロジェクトを組みました。

…やっぱLocalSRAMはSH2Aみたく1MByteくらいほしかったなーと感じますね。これ
100PinのチップですからSRAMもSDRAMも外に引き出すのがまた面倒ですし。実際に
204MHzの動作速度を生かしつつ何か作ろうと思ったらプログラムは128kByte以内に
必ず納めてフォントやテーブルなどの比較的低速でもよい大容量データは全部SPIFI
にうっちゃる等の工夫が要求されるでしょう。

SPFI-SPIROM上動作版のリンカスクリプトの冒頭はこんな感じになってます。


●OpenOCDで繋げて書き込む
現在のOpenOCD0.7.0では公式のソースにSPI-ROMとNxP固有のSPIFIドライバのパッチ
をあてて再ビルドする必要があります。私のぶろぐ上で提供しているOpenOCDの
バイナリ
はこのパッチを適用しています。(下述の書き込みスクリプトも同梱してます)

今回使用するデバッガハードウエアはJTAGKey2Cloneとします。後述しますがLPC4330
のエラッタにより外部リセットの直接操作が非常に重要となるのでリセット(SRST)が
使えるブツが必須です。
それとお気の毒ですがULINK-MEはOpenOCDにハードウエアレベルで対応していない
ので、一切使えません(ファームを書き換えた初代ULINKだけ可能です)!


さて、いよいよSPIFI-SPIROMにプログラムを書き込みます。SPIROMの消去を含む
操作をするためにはFlashのプロテクト解除を必ず行う必要がありました。これを省くと
書き込み時にエラーを返されて失敗します。

↑20130814追:少し前のコミットで修正されました。

↓書き込み時のメッセージは以下のようになります。
 書き込み直後にSRSTを直接操作して外部リセットを2度かけています。

>> "C:¥Devz¥Coreutils¥bin¥make.exe" program
openocd -s C:/Devz/ARM/OCD/tcl -f interface/ftdi/jtagkey2.cfg -f target/lpc4330_xplorer_spifi.cfg -c "mt_flash_bin main.bin 0x14000000"
Open On-Chip Debugger 0.7.0-dev-00001-ga4830e7-dirty (2012-09-24-10:03)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m3 reset_config sysresetreq
trst_and_srst separate srst_gates_jtag trst_push_pull srst_open_drain
adapter speed: 2000 kHz
Info : clock speed 2000 kHz
Info : JTAG tap: lpc4330.m4 tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : JTAG tap: lpc4330.m0 tap/device found: 0x0ba01477 (mfg: 0x23b, part: 0xba01, ver: 0x0)
Info : lpc4330.m4: hardware has 6 breakpoints, 4 watchpoints
Info : lpc4330.m0: hardware has 2 breakpoints, 1 watchpoints
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x10000428 msp: 0x10091fe8
background polling: on
TAP: lpc4330.m4 (enabled)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x10000428 msp: 0x10091fe8
Info : Found flash device 'sp s25fl032' (ID 0x00150201)
cleared protection for sectors 0 through 63 on flash bank 0
auto erase enabled
wrote 65536 bytes from file main.bin in 1.062507s (60.235 KiB/s)
shutdown command invoked
Polling target failed, GDB will be halted. Polling again in 100ms


なんでわざわざSRSTを直接いじっているかというとLPC4330-Xplorerに乗っかってる
チップのリビジョンは内蔵されたSPIFI-ROMドライバがPOR後の外部リセットした
後の初期化で必ずコケて次の外部リセットで正常に動くというイミフなerrataに
起因してます。
こいつのせいで今までうまくいった正攻法が全く通じずワークアラウンド満載な
書き込みスクリプトにせざるを得ませんでした。
まぁ結果的に安定したからOKということにしましょう。因みSRSTを繋げてなくても
SWD接続のversaloonやSTLink/V2で書くことはできますが、この場合いちいち
主電源を入り切りする必要が生じ面倒です。

また、デバッグ中に変なステートに落ち込んでJTAGのアクセスが一切不能に陥る
こともあります。この場合はディップスイッチでブート方法を別の経路にして
電源を入れ直すとひとまずJTAGで繋がるようになるので落ち着いてSPIFI-SPIROMの
内容を全消去してください(その後はブート方法をもとに戻すのを忘れずに)。


●OpenOCD+Insightでデバッグ

最後の仕上げにOpenOCD+Insightでソースコードデバッグできる環境も作りました。
こちらもワークアラウンド満載でgdbにattachしたときにsoft_reset_haltをかけて
プログラムの先頭で停止するようなトラップを仕掛けてます。

SPIFI-SPIROM上のプログラムを直接参照できるのでとてもありがたいですね♥
もちろんいつものIOViewでGPIOのビットの状態も一目でわかります♥
ちなみにGPIOの初期設定の時にInputBufferを有効にしておかないとピンの状態が一切
読めませんのでご注意ください!(普通のプログラムでも引っかかりやすいポイントです)


●SPIFI-SPIROMからブートしてSRAM上で実行してみる

SPIFIから実行すると大幅にパフォーマンスが下がってしまうので実際に使えるレベル
で試用するならばLocalSRAMからプログラムを実行する必要があります。SRAMの構成上
プログラムと初期設定値があるデータと合わせて128kByte以内に収めないといけない
制約が出来てしまいます。したがって大容量のフォントorデータテーブル等はSPIFI
におきっぱにしておくべきです。

今回はPCと連携せずにスタンドアロンで起動し、SRAM上で実行できる環境を拵えます。
原理としてはきわめて原始的なブートローダをSPIFIに仕込む形になりますが、大まかに
いうと以下の流れで行います。

1.SPIFIのアドレス(0x14000000)からブート

2.Reset_Handlerに飛ぶ(けどアドレスはまだSPIFI上の0x1400****)

3.".text"〜".data"の領域までLocalSRAM(0x1000000)にコピー

4.PCをSRAM上に指定してジャンプ

5.BSS領域をゼロクリア・各種クロック・I/O設定

6.main()に飛ぶ



"4."の部分がミソなわけですが実際のアセンブラのコードを見てもらうと…

一見無意味なことしてるように見えますがその場(SPIFI上)でジャンプすると着地点が
LocalSRAM上になりそのままSRAM上で何事もなくプログラムを継続できる仕組みに
なるわけです。
もうお気づきの方いると思いますが大昔AT91R40807でやってたことと全く
同じですね。

また、上記のからくりを実行するためにはbin形式でSPIFI-SPIROMに書いてやる
必要があります。
LMA/VMAの情報を保持しているelf・ihex形式だと失敗しますのでご注意を。



ということでLPC4330-Xplorerもこちらこちらに準拠したビルド・デバッグ環境を
こしらえました。
あとはどんどん上位層のプログラムを作りこんでいくだけです!


20121003追:
GCCビルド可能なLED点滅(シングルコア動作)プログラム公開します。

Go to top of page