« STM32のUSB仮想UARTモニター遂に完成 | トップページ | JTAGは気難しい。恐れていた事態が現実になる »

2009年5月13日 (水)

EclipseでARMのソースコードデバッグが出来るようになった

STM32基板にバッテリーバックアップ機能を組み込む(5/9/09)
 STM32でのUSBの仮想COMポート(VCP)がやっとのことで動き、がた老「AVR」研究所の「ARM」プロジェクトは大きく前進した。しかし、折角入れたJTAGとEclipseが活用できていない。ファームのコンパイルはDOS窓からだし、書き込みもDfu経由である。

 なりふり構わず当面の目的に突き進んでVCPモニターが動くところまでは行ったが、他は殆ど手がついていないままである。現在の開発手順、Dfuからのファーム書き込みは、沢山の画面を経由するだけでなく、ターゲットのモードをいちいちジャンパーピンで切り替えてリセットしなおさねばならない。いくらなんでも能率が低すぎる。

 Eclipseの環境は、前のLPC2388基板では実現し、STM32ではUART1を使ったGNUのサンプルがJTAGインターフェースで動くところまで進んだ。しかしどちらもまだ、止めたり動かしたりできるだけで、ソースコードデバッグまで行っていない。統合環境と言っても断片的にしか使えていない。目指す山はまだまだ高く、深い。

 それにSTM32基板の方は、Eclipseでビルドだけはやったが、ターゲットへのファーム書き込みはDfu経由である。参考にしているウェブサイトの書き込みスクリプトには、stm32x mass_erase 0というコマンドがあり、これは明らかに全部のフラッシュを消すコマンドで、これをそのまま使うわけにはいかない。Dfuを消してしまう。

 貧乏性というわけではない。JTAGでファームが間違いなく書ける保証がないのに、Dfuを消してしまうと、失敗したとき当面の書き込み手段をすべて失ってしまうのが怖い。これらとは別に書き込み手段があるのはわかっているが、そのツールのインストール、テストだけでもまた手間がかかる。余計な作業が増えるばかりである。Stm32vbat

 これは長年システム開発をしてきた人間の一種の職業病だろう。全体の所要作業量とリスクを最小にしようとして、些細なところに神経質になる。それで結果として先に進めなくなる。困ったものだ。それにしても、調べなければならないことが多すぎる。何から手をつけて良いかわからない。間口を広げすぎて完全な手詰まり状態におちいった。

 こういうときは気持ちを落ち着けるために何も考えないですむ手作業が良い。STM32基板にボタン電池(CR2032)をつけてRTC(リアルタイムクロック)のバッテリーバックアップの機能を実装することにした。付録基板を入手した直後、言われるまま手持ちのクロック用の32.768khzの水晶をハンダ付けしたが、電源をバックアップしていなければRTCは何の意味もなく宝の持ち腐れである。これでこの部品の顔も立ててやれるというものだ。

 付録LPC2388基板のバックアップ用の電源ピンVbatは、Vccにパタンで直結されてしまっているが、このSTM32基板は感心なことに配線図を見ると0Ωの抵抗(R1)でVccにつながっている。0Ωの抵抗なんて何の役に立つのだろうと以前は思っていたが、これはアイデアである。表面実装のこのチップ抵抗を外して、ここへバッテリーからの配線をつなげば電源回路を簡単に分離することが出来るからだ。

 久しぶりにハンダごてに電気を入れる。配線図のR1は基板上ですぐ見つかった。クロック用の水晶のすぐ近くにある。隣に並んでいる0.1μのパスコンまではずしてしまわないように、慎重にチップ抵抗だけにフラックスをつけ素早く両側を暖めてハンダを溶Stm32vbat1かす。

 とれた。いけない。0Ωの抵抗チップがどこかへ吹っ飛んでしまった。これを探すのはさすがに止めた。電池フォルダーをベース基板に固定しUEW線で接続する。予想していたより早く簡単にバックアップ回路が完成した。これでSDカードの書き込みで正しいTODを記録することができるし、目覚ましやタイマーなど応用の範囲が広がると言うものだ。楽しみである。

ARMとGDBの参考書を買ってきた(5/10/09)
 ARMにしてもEclipseにしても雑誌とウェブの情報だけでは、どうしても断片的な知識になりやすく系統的な知識がなかなか身につかない。今の行き詰まりを打開するためにも、ここはひとつちゃんとした参考書で基本的なところを押さえようと、このあたりでは一番本が揃っている新宿の紀伊国屋本店に足を運んだ。

 ARMの参考書はいくつかあったが、どうも帯に短し、たすきに長しである。結局、「ARM組み込みソフトウエア入門 」CQ出版社¥4,620を選んだ。この本、入門と銘打つわりには店頭にある本の中で、一番高度な内容が書かれており、参考になりそうだ。 ついでにクロス開発用のGDBの参考書「GDBを使った実践的デバッグ手法」CQ出版社¥2,310も買う。Arm

 結果から言えば、この2冊とも、今こちらが直面している具体的な疑問には何も答えてくれなかった。どちらも今の自分には少しレベルが高すぎるようだ。背伸びはするものではない。2年前AVRを始めたとき、PINとPORTを間違えて動かない、動かないと悩んでいたことを思い出した。現在の問題(割込みを止められない、外部変数をループで待っても変化しない)は余りにも基本的な事なのでそれに関することは何も書いていない。

 ただ、ARM入門のほうで、スピード向上とフラッシュの節約のためCでは1バイト変数ではなく、4バイト変数を使えと言う説明は参考になった。Gdbもちろん変数を入れるSRAMとのトレードオフになるが、ARMのレジスターとメモリの受け渡しはすべて4バイト単位なので、1バイトにするために無駄なコードが発生するのだそうである。

 GDBの本の方は、直接は何の参考にもならなかったが、皮肉にも今まで悩んでいたコマンドがすべてOCD(On Chip Debugger)のコマンドであることがわかり、ウェブにあるWikiのOCDのコマンドマニュアルを読むことで、結果として飛躍的に知識レベルが上がった。マニュアルは英語だけで、日本語訳がないが、ここに抄訳がある。

 マニュアルを読むうち、OCD のflashコマンドに必須のバンク番号という意味がやっとわかった。STM32 などはフラッシュメモリが一組しかないので、0で良いのである。組み込み系では常識なのだろうが、私のように大型機育ちで、バンク、セグメントが乱立する86系を毛嫌いし、Z80のザイログやモトローラ(Macintoshでアセンブラを少しやった)のリニアなアドレス空間を好んでいた人間にはバンクの概念が薄い。

 昔話はさておき、少し気分が落ち着いてきたのでARMプロジェクトの懸案事項を整理し優先順位をつけて作業を始めることにした。10余りの懸案が揃った。ひとつのグループは先のARMのコードに関する懸案、次がOCD、GDBのデバッグ環境、もうひとつはEclipseの全体環境の懸案である。このEclipse、作業名がプロジェクト単位に独立しておらず、スクリプトをすべてユニークな名前にする必要がある。それでいてやることは同じだ。どうも矛盾があるような気がする。しかし何かまた勘違いしているのかもしれない。

GDBが知らないうちにフラッシュを書いていた(5/11/09)
 とりあえずはデバッグ環境の整備が一番優先順位が高い。コードの問題解決やEclipseの環境整備は、その先の話とする。 で、ひとつ前のUART1で動くプロジェクトをEclipseで開けるようにした。STM32 基板のJTAGインターフェースは、この前実装し、Telnetレベルで動くことを確認しただけでEclipseで動かすのは始めてである。ファーム書き込みは前に書いたように出来ないので、GDBだけでも動くのを確かめようと、OCDのスクリプトを書いてテストしてみた。STM32のフラッシュは前のVCPモニターのままである。

 違うフラッシュに別の情報を持ってGDBが立ち上がるのだから、すぐ止まるだろう。動くことが確認できれば良い。予想通り、GDBは沢山のエラーメッセージを出して、普通はエラーリターンするところを、怒りすぎたのか死んでしまった(GDBコマンドがkillされた)。

 まあ、これは想定どおりだ。しかし、エラーメッセージを頭から見直して行って顔が青ざめてきた。GDBはフラッシュにどうもイメージを書き込んでいる。エラーは別のところだ。 確かにOCDのGDB起動スクリプトには、load main.elfというステートメントがある。これはGDBのPC側の実行空間にelfファイルを展開しているのだろうと思っていたのだが、どうもそうではなさそうだ。

 これはいかん。Dfuを消してしまったか。UART1のプログラムはDfuを避けてロードされるはずなので大丈夫だとは思うが心配だ。折角ここまで我慢してDfuを残しておいたのにと、あわてて、基板のピンをDfuモードにしてPCでDfuローダーを立ち上げる。

 良かった。Dfuは消されていなかった。Dfuローダーにファームの存在を示すメッセージが出た。胸をなでおろす。ということは、前のUART1のイメージがフラッシュに書かれたのか。半信半疑で、STM32基板のUART端子をつなぎPCのUART端末を開く。

 はっはっは。 端末からはADコンバータの数字が出力され0,1のキーでLEDが点滅する。UART1のプログラムがちゃんと動いている。知らぬ間にGDBがフラッシュに正しくファームを書いてしまったのだ。このあいだからフラッシュへのファーム書き込みは、TenetからのOCDコマンド入力でさんざんテストしていたのだが一度も成功していない。

 その都度、セクター番号が違うだの、プロテクトされていて駄目だの、書く前にフラッシュを消しておけだのと叱られて門前払いを喰らっている。それがいとも簡単に出来てしまった。GDBがさっきの煩雑な手続きを全部済ませてしまったのだ。

Eclipseでソースコードデバッグが出来るようになった(5/12/09)
 期せずしてJTAGによるファーム書き込みに成功して、プロジェクトは更に進んだ。もう、これでDfuをいつでも消せる。JTAGで書けるので、必要ならDfuをrestoreすることができる。残った基本的な機能の実現は、GDBによるソースコードデバッグである。

 それにしても、この環境は、ウェブでこぼしていた人がいたように、複雑で、一筋縄では行かない。EclipseとOCD、それにGDBの3つの環境がそれぞれ並列的に動いている。
Eclipseとは別にTelnetを開きコマンドレベルで色々いじっていると、何が何だかわからなくなってくる。

 しかも、EclipseはもともとはJAVAの統合環境なので、GNUのC/C++の開発環境はあとから加えたプラグイン的な扱いであり、どうもしっくりこない。しかし機能の豊富さは大変なものだ。まだ殆ど理解できていないが、数え切れないくらいの沢山の機能がある。

 でも、ソースコードデバッグは、あっけなく実現した。参考にしていたウエブサイトは、このあたりから「ご自分でどうぞ」という姿勢なのでもう頼りにできず、心配していたが、ほどなく必要なGDBコマンドが見つかった。symbol-file  <ターゲットファイル> である。必要なリソースは、GDBが勝手に探してロードしてくれるらしい。Ws000000

 早速、GDBの起動スクリプトにこのコマンドを入れて試してみる。おお、動いた動いた。フラッシュ上のコードなのでブレークポイントの数が少ないが、止まったところのソースの行番号を表示しhaltしてくれる。しかし、VCPモニターをデバッグしたところ、USBのタイムアウト(?)でステップごとのデバッグは無理とわかる。どうもタイムアウトが起きてすぐHardエラーのルーチンに飛んで行ってしまう。このあたりが、私がICEを敬遠してきた理由である。外部条件を良く考えて動かさないと、まともなデバッグが出来ない。まあ、ここも奥の深い世界だ。あわてずじっくり進めていこう。

 先月からほぼ丸1ヶ月、ARM環境整備プロジェクトはこれでおおよその目標を達成した。まだまだほんの入り口に立ったにすぎないが、STM32の開発環境は一応揃ったことになる。これからは楽しいプログラム開発が待っている。まずRTCを組み込んで時計を作ってみよう。SDカードソケットが実装されているので、ここでもファイルシステムを入れてSDカードプレーヤーARM版にしても良い。裸ではコーディングが面倒なので簡易なOSを入れたほうが良いかもしれない。夢がふくらむ。

|

« STM32のUSB仮想UARTモニター遂に完成 | トップページ | JTAGは気難しい。恐れていた事態が現実になる »

ARM」カテゴリの記事

コメント

早速のコメントありがとうございました。
そうか、やっぱり最適化が原因のようですか。
そう言えば、externにはvolatile宣言をしてませんね。

すぐ確かめてレスポンスしようとしたところ、突然、
JTAGが言うことを聞かなくなり(Block R/W error)、確認することが出来なくなりました。返事が遅れて申し訳ありません。Dfuをつぶしたのが原因らしく、どうも、ねむいさんの手法を頼りにすることになりそうです。(flash bank write_imageはoffsetしておかないと頭から書いてしまい、HardErrorになってJTAGがおかしくなる)

投稿: がた老 | 2009年5月20日 (水) 12時42分

たびたび失礼します。ねむいです。


「外部変数…」の部分、昨年末に右も左もC言語すらもロクにわから
なかった当時の私がモロに嵌ったところです…まず以下のことを試して
みてください。もしすでに試されていたら以下の発言は無しで…

1.最適化レベルを0にして(-Osなら → -O0にする)コンパイルし、
  問題が発生しないか確認する。

2.1.がうまくいったら最適化レベルを元に戻して、 
  main.c内のextern uint32_t count_out;の宣言を
  extern volatile uint32_t count_out;に書き換えてコンパイル
  し、確認する。

↑の二つがうまくいったらコンパイラの最適化の問題です。
Sourceryだと2007q3-53より後のバージョンでコンパイルすると
この問題が浮上します。STM32のV2.0以前のデモコードがリリース
されたころはそこら辺のことがまだ考慮されていませんでした。

ループ内で関数呼び出しを行うと最適化されずにうまくいくのは
count_outが呼び出した関数内で変化する可能性アリとコンパイラが
判断して最適化しないからでしょうね。

V3.0.1のUSBライブラリ内のデモ見た限りではこの問題はさりげなく
修正されていました。私の日記にCodesourcery/RaisonanceRIDE7向けに
V3.0.1のVCPデモコードをポーティングしたのをアップロード
しましたのでよろしければそちらも試してみてください。

投稿: ねむい | 2009年5月18日 (月) 20時48分

有力な情報ありがとうございました。
ブログのURLがあったので読ませて頂きました。おお、これは情報が盛り沢山ですね。こちらこそ参考にさせてください。私も迷ったけれどLattice基板付録の雑誌買ってしまいました(まだ封も開けていない)。
 ところでARMにお詳しいと見ていきなり質問ですが、STM32ではユーザープログラムでループしているとき、外部変数は、NOP_process( )などの別のプログラムをCallしないと変化しないものなのでしょうか。あれからいくら探してもこのあたりの情報が見つかりません。もし何かご存知でしたらコメント頂ければ幸いです。

投稿: がた老 | 2009年5月17日 (日) 17時58分

はじめまして。

AVRやSTM32の製作記事、いつも大変参考にさせていただいております。


JTAGでアクセスできるようになると確かに便利になりますが、
STM32の開発の際に一度それで嵌ったことがあります。

STM32はCPUのコアクロックが停止するような命令(__WFI命令等)
を実行しっぱなしになるとJTAG経由のアクセスができなくなって
しまいます。私も過去にその命令を含むプログラムでDFUを書き潰して
JTAGで一切アクセスできなくなってしまい壊したと思って焦りました。

そうなった時はSTM32内にあるシステムメモリからのブートでシリアル
経由でフラッシュの消去により回復ができます。もしこれからの
開発で、急にJTAGにアクセスできなくなったー!なんて状況に陥った時は
シリアル経由での書き換えのことを思い出して試してみてください。

自分のブログにも書いていますが私は頻繁にチョンボしてたので、自作の
拡張基板にDFU起動用とシステムメモリ起動用のタクトスイッチを
二つ設けてしまいました。

投稿: ねむい | 2009年5月15日 (金) 01時12分

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック


この記事へのトラックバック一覧です: EclipseでARMのソースコードデバッグが出来るようになった:

« STM32のUSB仮想UARTモニター遂に完成 | トップページ | JTAGは気難しい。恐れていた事態が現実になる »