2011年7月4日月曜日

JTAG接続不可からの修復成功

Setellaris関連で開発を行うときは、CodeSourcery G++(ARM)OLIMEXのJTAGエミュレータARM-USB-OCDOpenOCDを組み合わせて使っているわけだれど、これまで何機種も開発してきて初めておかしな現象に出くわしたので、ここに記録しておく。

おかしな現象とは、JTAGエミュレータがStellarisにまったく接続できなくなった、ということ。
OpenOCDを起動すると、次のようなメッセージが出た。
Open On-Chip Debugger 0.2.0 (2009-09-02-13:49) Release
$URL: http://svn.berlios.de/svnroot/repos/openocd/tags/openocd-0.2.0/src/openocd
.c $
For bug reports, read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS
100 kHz
jtag_nsrst_delay: 100
jtag_ntrst_delay: 100
     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr
---|--------------------|---------|------------|------------|------|------|------|---------
 0 | sterralis.cpu      |    Y    | 0x00000000 | 0x4ba00477 | 0x04 | 0x01 | 0x0f | 0x0f
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* sterralis.cpu      cortex_m3  little sterralis.cpu      unknown
Info : device: 4
Info : deviceID: 67353818
Info : SerialNumber: 0B010030A
Info : Description: Luminary Micro ICDI Board A
Info : JTAG tap: sterralis.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0
xba00, ver: 0x4)
Info : JTAG Tap/device matched
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Block read error address 0xe000ed00, count 0x1
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
Warn : Timeout (1000ms) waiting for ACK = OK/FAULT in SWJDP transaction
"Warn : timeout(1000ms) …"と延々と出続けて、何の操作もできなくなってしまっていた。
でもだいたい察しはついていた。というのも、最初はちゃんとJTAGでこのCPUを認識していて、この現象が出始めたのは新規に開発したコードを書き込んでからだったからだ。おそらくJTAG関連のピンがGPIOモードに変更されたか、CPUがスリープモードに落ちてJTAG自体も機能しなくなってしまったかどちらかだろう。

Stellarisの"困ったちゃん"なところは、ハードウェアリセットピンをアサートしているとJTAG機能まで停止していることだ。今回のように間違ったソフトウェアを書き込んでしまうと、リセット解除直後にその間違ったコードを実行してしまいJTAG接続ができなくなる。リセット解除からJTAG機能が落ちてしまう数~数十us以内に強制ブレークさせることができればよいのだが、それは至難の業。困った。

Stellarisのデータシートを読んでみると、"Recovering from a locked microcontroller"という章があるのを発見!更に、最新のOpenOCDには"stellaris recover"というコマンドが追加されていることも知る。これを使えば回復できるかも!と期待して、わざわざOpenOCDの最新ソースをgitリポジトリからDL&コンパイルしてみたが、やはり動かない。というのも、OpenOCDの"stellatis recover"コマンドは"init"コマンド以降でしか使えないようで、現状ではその"init"コマンドの実行中に例のWarningが表示されて止まってしまうのだ。つまり、せっかく「カギ」を見つけたのにそのカギはカギのかかった箱の中にあった、というようなもんだ。

仕方がないので、最終手段としてデータシートで見つけた"Recovering from a locked microcontroller"に書いてある手順を自分でコーディングしてみることにした。幸いにもJTAGデバッガはFT2232MPSSEを使用するようになっているので、簡単なライブラリ呼び出しで実行できるはず。で、サクッと作ってみたら・・・直った!再度、JTAGデバッガ+gdbから書き込みができるようになった。

しかし、ここまでで何時間をムダにしただろう。JTAGデバッグ機能って、デバッグ時の重要な砦なのにそれが使えなくなるようなマイコンの仕様っていったい・・・ブツブツ

0 件のコメント:

コメントを投稿