カテゴリー「ARM」の11件の記事

2009年7月16日 (木)

LPCMプレーヤー2号機開発の道草

LPC2388のRTCバッテリーバックアップに挑戦する(7/12/09)
 思わぬ道草を食ってしまった。ストロベリーリナックスのミニ液晶表示装置を2種類のIICで動かすライブラリを開発して、ちょっと自慢したくなり、ショップの問い合わせフォームで報告したら、あのPICNICで有名な社長の落合正弘氏ご本人がすぐメールを返してくれた。ショップへのこうした連絡はなしのつぶてということが多い。誠実な態度に感激した。

 記事をアップしてからすぐ「ねむい」さんからコメントを貰い、ソフトIICのDDRの謎はいっぺんに解けた。冷静に考えれば、出力ポートを最初0にしておけば、ポートをハイインピーダンスの入力から出力に切り替えれば、そのポートは0になるというのは自然なことだ。 もっと早く気が付くべきだった。そのうえ、リリースしてからすぐバグを見つけてしまい、少しめげている。

 ソースコードを見ていただければわかるが、欲張ってスクロールしようと思ってコードを追加したらあまりにも遅い(クリアに1msかかる)ので元へ戻したあと、テストを十分していなかったのが原因である。くやしいので、クリアをやめてDDRAMにデータとブランクを書き込む手法もあとから試したが、これもあまりスクロールに見えない。2行程度では難しいようだ。余計落ち込む。

 こういうときは、手を動かしていやなことを忘れるに限る。前々からやろうとしていたARMのもうひとつの雑誌付録基板、LPC2388のバッテリーバックアップ配線に挑戦することにした。前の記事では、これはとても無理だと書いたが、このあいだChaNさんの掲示板にある動画で、ご本人が苦もなく、0.5ミリピッチで並ぶピンを切り、配線しているのを見てしまった。うわあ、出来るんだ。驚きと同時に勇気を奮い立たせてくれた。A7112057

 しかし、手持ちの道具では、あんな細いピンを切ることは不可能だ。市販の超極細ニッパの刃先は0.3ミリというから、これで切れるのかもしれないが、出来るか出来ないものに¥2000近く投資するのも何か馬鹿らしい。

 で、暫く様子を見ていたが、たまたまアートカッターというクラフトワークに使う極細のカッターがあるのをウェブで発見した。刃先の厚さが0.38ミリだと言う。これなら切れるかもA7152071しれない。値段も¥500から¥1000前後で手頃だ。他の用途にも使える。東急ハンズを覗いてみたら沢山あったので手頃なカッターを2本買ってみたが、すぐには取り掛からずにいた。

 ところが、さらに強力な武器が思わぬところから手に入ったのである。このところ持ち歩いているSDカードプレーヤーを久しぶりに訪れたなじみのパブで自慢したら、何を考えたかマスターが奥からLED照明つきのヘッドルーペを持ち出してきた。使ってくれと言う。先日亡くなった母が使っていて誰か使ってくれる人がいないか探していたのだそうだ。渡りに船とはこのことだ。有難く頂戴した。

 道具が揃った。ヘッドルーペをつける。少し重いが、3倍の拡大率で視点を自由に変えられるので、A7112060作業しやすい。カッターで少しづつVbatピンを削って切っていく。これがなかなか難しい。ニッパーならあっという間だろうが、隣のピンを痛めずに一つのピンだけを切るのは簡単ではない。しかし始めてしまったらもう切るしかない。切り屑が出てきて切れたか切れないかルーペを通しても良くわからない。別のピンを切っていたら最悪である。何度もピンを数えて確認する。

 隣のピンも何か傷んできたようだ。これはまずい。もうやめようかとあきらめかけた時、Vbatピンが浮き上がってきた。おおお、切れたようだ。A7112063切り屑を針と洗浄剤で掃除して、テスターで切れたことを確かめる。よし、大丈夫だ。隣も確かめる。OK。いやあ冷や汗をかいた。

 切断に較べたら、半田付けは気分的に楽だ。この前の1608のチップ部品のハンダ付けの経験が生きている。問題は線の引き回しだ。基板上にピンヘッダーを横置きしてボンドで固め、ここにVbatピンか ら引き出した0.2ミリのUEW線を配線する。

A7112068 ベース基板にCR2032のフォルダーを付け、やっとのことでLPC2388のバッテリーバックアップ配線は完成した。いや楽しかった。こういう細かい手作業はいやなことを忘れさせてくれる。テストは...2号機が出来るまでお預けにしておこう。

EAGLEの入門書を買ってきた(7/15/09)
 色々道草を食ってきたが、2号機開発の作業は遅々としているとは言え、少しづつ進んでいる。ソフトパワースイッチは、大体目処がついた。FatFSが丈夫になったので、ソフトがハングして、電源が切れなくなる可能性は少なくなったが、今のスイッチルーチンの構造は、スイッチが離されるまで外へ出ないので、この構造は変える必要がある。押している間に、LCDが動き始めたり、消えたりしないと、操作性が悪い。

 まあ、これはソフトの世界なのであとから何とでもなる。ミニLCDが動いたので、ソフトの懸案は大体片付いた。いよいよメイン基板の具体的な設計に入る。

 その前に、バッテリフォルダーの制作にかかる。エポキシ系の接着剤が強力なことがわかったので、1号機で苦労した電池接点基板は、ケースの三方に接着するだけで必要な強度はとれそうである。汎用基板をルーターのカッターで切り出し、やすりで削ってケースに合う電池接点基板を作る。A7152084

ここへ、燐青銅線の接点をつける。このあいだの充電基板で試した形状の接点が簡単で具合が良いので、同じ型にする。経験が生きている。簡単につけることが出来た。テスターで電圧を測る。うむ、軽く当てるだけで安定した電圧がとれている。快調である。これなら複数台をこなせそうだ。

 メイン基板のレイアウトをもういちどやりなおす。充電回路も組み込むのでさらに大変である。部品が全部乗せられるかどうもかも自信がない。しかし、今度のメイン基板は、横の電池と同じ高さなので、配線A7152076 側が7ミリ近く空いている。いざとなったら、抵抗などはこちら側に入れることができるのでなんとかなるだろう。

 それより大きな懸案は、配線である。汎用基板にUEW線で配線することにすっかり慣れてきており、これくらいの密度でも配線できる自信はあるが、同じものを複数作れるかというと、とてもその気力はない。今回のプレーヤーは少なくとも3台は同じものを作らなければならないことになりそうである(身内1台、ヘッドルーペを貰った店1台、会社1台)。

 となると、プリント配線である。しかしこれはこれまでの工作とは全く違う大変な作業だ。もとより感光基板から作ることは考えていない。大掛かりな道具立てが必要で、今要求されているような精度の基板が作れるようになるまでには、気の遠くなるような時間がかかるだろう。現実解としてはCADで設計図を描いて、外国に発注すると言うのが一番有力なコースである。

 今までに何度か、これをやってみたい気になったことがあ36301lるが、これはこれで相当な心構えと準備が必要なのでそう簡単に始められるものではない。

 しかし、機は熟してきたようである。CADの定番、EAGLEの勉強を始めることにした。これが道草になるのかどうかは議論のあるところだが、手配線でも出来ることをCADでやろうというのだから道草の内に入るだろう。とはいえ、これがアマチュアの強みである。誰に束縛されるわけでもない。自由に自分のやりたいことができる。

 ウェブには、沢山の経験記やノウハウが載っているが、ここはオーソドックスに全体を見渡せる勉強法にしよう。書店で、「プリント基板CAD EAGLE活用入門」(\2800)という参考書を買ってきた。読み始める。また新しい登山口に立った。頂上は見えないが、未知との出会いに心が躍る。

| | コメント (1) | トラックバック (0)

2009年6月 8日 (月)

STM32基板のRTCを動かす

 それにしてもデバッグは難しい。わかってしまえば、何でこんなことに今まで気づかなかったのだろうというお馬鹿な間違いなのだが、気がつくまでの道のりは決して短くない。まあこの謎解きが面白くて電子工作をやっているようなものだが、今度のSTM32のRTC(リアルタイマークロック)プログラムも結構手こずった。「デバッグは外へ、外へ」などと偉そうなことを常日頃言っているくせに、頭に血が昇るとつい我を忘れてしまう。

軽い気持ちで手をつけたがまるで動かない(6/2/09)
 このところ1年前の雑誌の付録基板、STM32F103(Cortex-M3) の開発に熱中し、先週、高速化したUSB仮想UARTのモニタープログラムを完成させて意気が上がっている。ウェブでもこの石を使ったCPUボードを時々見かけるようになった。価格もそう高くない(2インチ160x128のカラー液晶付きの評価ボードが¥9000で手に入る)。クロック72Mhzの32ビットプロセッサーだ。ARMコアの中では普及版だそうだが、アマチュアが遊ぶには十分すぎるスペックである。

 RTCはUARTモニターの開発のときから次の目標に決めてある。せっかくバッテリーバックアップ回路を追加したのだ。電池と32.767khzのクリスタルの顔を立ててやらねばならない。RTCはファイルシステムには欲しい機能だし(書き込みの記録)、これが動くと俄然マイコンがプロっぽくなる。幸いSTマイクロの提供するライブラリには、RTCのライブラリを使ったデモソースが収録されている。これを使えば簡単に出来るはずだ。Stm32vbat

 早速Eclipseの新規プロジェクトを作り、そこへソースコード一式を放り込む。このソースはIARなどの開発環境用なので、仮想UARTモニター同様、GNUで必要な、Makefileや、リンカースクリプト、スタートアップルーチンを入れて調整する。Makfileを換えるだけでうまく行くはずだ。必要なライブラリを取捨選択し、ビルドする。殆ど問題なくバイナリーが出来た。

 わくわくしながら、フラッシュローダーにかける。おやあ、赤ランプがついて送れない。ええー、hexファイルがないだと? ほんとだ。ファイルはあるけれど中身は0バイト。これは一体どうしたことだ。elfファイルは60KB以上あるのに。コンパイラーもリンカーもエラーは出ていない。こうなると何が悪いのか見当がつかない。

 マップファイルは出来ていたので、良くわからないままこれを調べる。あれ、関数のエントリーがみな同じ値だ。これはおかしい。でも、エラーは起きていない。念のため、必要なライブラリの数をMakefileで確かめる。一つ少ない。あれえ、stm32f10x_vecter.cが抜けている。デモソースのreadmeには、これを入れろとは書いていない。

 何と言うことだ。こいつがないからに違いない。とにかくこれを含めてビルド。おお、ちゃんとしたhexファイルが出来た。readmeを信じてえらい目にあった(このあと各開発環境のプロジェクトフォルダーにはこのモジュールが入っているのを発見した。GNUのときは注意しないといけない)。それにしても、ビルドやリンクのときのNO ERRORは安心できないことを学ぶ。

 お膝元のメーカーのデモソースである。バイナリーが出来たので簡単に動くかと思ったが、これが全く動かない。おかしい原因はおおよそ見当がついている。UARTへの出力関数printfが恐らく暴走の原因だ。これを、これまで使っていたsprintfに置き換え、受信関数も自前のものにして再度、実行。

 おお、やっとメッセージが出た。しかし、RTC not configured...のメッセージを出したまま、それっきりになる。ロジックを追うと、RTCのセットアップが終わるのをループで待っていて、ここがreadyになっていないようだ。やれやれ、ハードか。念のため電圧を測る。3.24V。この程度なら問題ないはずだ。オシロで周波数を確認する。立派に32.767khzが出ている。大丈夫だとは思うが、要因を減らしてみよう。

 バッテリーバックアップをやめてVccにつなぎなおす。うわあ、RTC configuredのメッセージが出て先へ進んだ。何だ、何だ。電池が原因か。何か部品が足らないのか。

 ハードの問題は別として、これでうまく行ったと思ったら、そうは問屋が卸さなかった。時刻の設定をする受信関数が、がんとしてデータを読まない。受信関数は自前だ。自信がないので、プログラムの頭でテストステートメントを挿入してみた。いや、ちゃんと動く。しかし、時刻設定の入力では、受信データのフラグがあがらない。

 それにしても、UARTぐらいの機能で、このソースの複雑さは何だ。読みにくいことおびただしい、と悪態をつきながらデバッグする。また最適化が原因かと思ってループに、NOP_Processなどを入れるが変わらない。UARTなら、このあいだのGNUサンプルソースにもあった。こちらは至極簡単なソースだ。こいつを持ってきて動かすが、これも駄目。万策がつきる。

原因はUARTではなかった。あっけない幕切れ(6/5/09)
 UART受信が出来ない。本質と関係のないところでつまずいている。RTC不調も電池でない可能性が強い。電源を入れたままリセットをすると、RTCの初期化が途中で止まる。

 UARTの方は、その後ステータスレジスターを問題のところで出力させ不正なビットが立っていないことを確認した。どうもUARTがハングの原因ではなさそうだ。LEDとUART出力を処理の始めから、少しづつ挿入し、ハングアップするステートメントを探していった。

 その結果、RTCの割込みをenableするところでハングすることがわかる。RTC割込みがおかしい。試しに割込みルーチンにLEDを点灯するステートメントを入れるが、点かない。そうだこれに違いない。

 デモソースのバグは考えられないので、これは明らかに、Dfuのためにずらしたプログラムのエントリーアドレスが、ベクターテーブルに反映されていないことを物語る。しかし、ソースの何処を探しても、テーブルのアドレスを設定するところはない。ベクターテーブルは、リンカーの最初のプログラムのスタートアドレスから相対的に展開しているからだ(これが大きな勘違い)。そうすると、リンカースクリプトか、スタートアップルーチンか。しかしここは良く分からないところで手が出せない。

 思い余って、最近お世話になっている「ねむい」さんが、RTCを動かしたと言うので、質問しようかとページを開いたら、ソースを公開されている。質問する前に調べてみようとありがたくソースを頂く。(会社ではダウンロードできなかった)

 おお、このソースは情報の宝庫だ。ユーザープログラムで割込みを止めるステートメントもある。で、ベクターテーブルを設定するところは、どこだ。見つかった。あ、あ、あ、なーんだ。明示的に設定するのだ。

void NVIC_Configuration(void)
{ NVIC_InitTypeDef NVIC_InitStructure;
  /* Set the Vector Table base address at 0x08003000    for Dfu  */
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000); 

 早速、このステートメントを追加し、コンパイルしなおす。苦もなく動き始めた。全く問題ない。1秒ごとにLEDが点滅し、UARTに時刻が表示される。RTCの出来上がりである。これで、この週始めから悩んでいた問題がすべて解決した。いやあ、知らないと言うことは恐ろしい。NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); のステートメントでもあれば気がついていたかも知れないが、それにしても「ねむい」さんに感謝である。Stm_rtc

 しかし、何故、割込みが原因だということに気がつかなかったのだろう。UARTの不具合と頭から思い込み、こればかりを追求していた。RTC割り込みは1秒である。ちょうど時刻設定の入力と重なる頃だ。一瞬入力が出来たときもあり、少し冷静に考えれば、このとき不具合がUARTでないことにもっと早く気がつくべきだった。

 電池が入っているときに動かないのは、時刻設定をしないで単に時刻表示に行くからで電池が原因でハングアップしていたわけではない。しかも、付録の雑誌の7月号には、このベクターのオフセットをしないとデモなどは動かないよ、とわざわざ解説がステートメント付きで載っていて、これを読んでいたはずだ。この前の仮想UARTのhw_config.cにもちゃんとベクターのシフトがコーディングされている。今になって考えるとヒントはそこらじゅうにころがっていたのだ。お恥ずかしい限りである。

| | コメント (10) | トラックバック (0)

2009年6月 1日 (月)

ダブルバッファーでUSB仮想UARTの内部速度が2Mbps

しゃれた実装を考えたが挫折(5/28/09)
 SysTickタイマーで1ms単位の経過時間が測れるようになったので、勇躍、STM32基板のUSB仮想UARTの高速化にとりかかった。これまでにわかっていることは、UARTの速度が遅いときは問題ないが、早くなってくるとエンドポイントの送信終了の割込みがユーザープログラムがデータを移している最中に入り、このときのデータサイズが実際のデータと不整合が生じてデータが欠落する。

 これはSTマイクロが提供するSTM32F(Cortex-M3)用のVCPデモプログラムに最初からあった問題で、STマイクロのフォーラムで去年話題になり議論されていた。少なくとも私の知る限りまだ解決していないはずである。SysTickを使って改修されたコードがアップされたが、その後本人が動かないとして取り下げている。この解決を当研究所がやろうというのである。もしうまく行けば鼻が高い。

 方式はダブルバッファー方式である。前のDACのデコードと同じような考え方だ。ひとつのバッファーをユーザーの送信関数の書き込み用とし、ここに送信データを入れていく。送信関数ではエンドポイントに直接書き込まない。ここで書き込むと、書き込み終了の割り込みがどこで起きるかわからないからである。もうひとつのバッファーは、割込みルーチンが既に書き込み処理をしたデータが入っている。

 書き込み終了の割込みがかかり、割込みルーチンに制御が渡ったときに、バッファーをスイッチして、今度は送信関数が書き溜めていたデータをエンドポイントに書き込む。さきほど送り終わったバッファーが今度は送信関数が新たに書き込むバッファーとなる。これで、データ書き込みと送り出しの衝突を避けることができる。

 最初、コードを少なくするため、2組必要なバッファー配列とカウンターをポインター変数にし、そのアドレスをスイッチして動くようなスマートな方式でコードを組んだ。
バッファーに送信バイトを送り込むとして、

 * ( バッファーアドレス +  * カウンター++ )=  送信バイト;

みたいなプロっぽいコードである。バッファーアドレスとカウンターポインターを取り替えるだけで、main.cの送信関数USB_Putc()はダブルバッファーであることを知らないで済む。いやコーディング技術も格段に進歩したものだ、と、得意になって完成させた。ロジックはそう難しいものではない。気をつけないといけないところは、バッファーを切り替えるときに、ユーザープログラムの実行と重ならないように、フラグを立てて守るということである。今度は、割込みルーチンが見えているので、ユーザー側は、そのフラグを見て待てばよい。

 と、これが全くうんともすんとも言わないのである。どうもさっきのステートメントのところで暴走している。表記に間違いはないはずだ。何度もウェブなどで確かめる。うーむ、何か勘違いがあるのだろうか。プログラムはまさしく考えたようには動かない。書いたように動くだけだ。いずれにしても、ポインターを使ったコーディングは一歩間違えば、とんでもないところにデータを書き込み、簡単に暴走してしまう。

 色々いじったが好転しない。悩んだ挙句、この方法をとりあえずあきらめ、普通の配列を使い、愚直に2組のバッファーを別々に操作するルーチンに切り替えた。さあ、これでどうだ。これなら暴走しようがない。もう問題ないはずだ。

 ありゃりゃあ、これでも動かない。ええー、どこが悪いんだ? シングルバッファーに戻すと何事もなく動く。わからない。このあたりでGDBが使えれば良いのだが、今のままでは、USBを使っているので初期化の段階で、HardFaultに落ちてしまいメインループに来ない。環境を大きく換えないと使えない。別のUARTで変数を出してデバッグする手もあるが、どちらも手間がかかる。

ダブルバッファーが動いた!しかしこれで良いのか(5/29/09)Ws000000
 開発が暗礁に乗り上げている。マラソンや登山と同じだ。この苦しみが歓喜の材料なのだが、その最中はそれどころではない。大げさに言えば人生が暗い。今まで生きてきたことすべてが意味のない時間だったような気分になる。

 BeagleBoardのために久しぶりにモニターを取り替え、1920x1080のワイドディスプレイになって開発環境は一変し(エディターと端末が同時に見られる)、快適になったのだが、気分は優れない。救いは、このあいだの第三のファーム書き込み手法ROMのフラッシュローダーが思いのほか使い勝手が良く、プログラムの修正、ビルド、ファーム書き込みのサイクルが飛躍的に早くなったことである。AVRなみの開発環境である。Eclipseは編集とビルドだけにしか使っていないが、これはこれで便利だ。

 それはともかく、ダブルバッファーが動かない。基本的なところを少しづつ確認していくしかない。何回目かのコードレビューの最中に、ふっと気がついた。送信関数は律義にバッファーにデータを溜め込み、一杯になれば、割込みルーチンがバッEclipeファーを切り替えるのを待っている。では誰がUSBのエンドポイントに書き込むのだ。あ、あー、ここだ。エンドポイントに書き込む処理は、エンドポイントに書いた後の割込みルーチンにしかない。ポインターの暴走でもなんでもない。元から動かない。

 何と言うお馬鹿なコードだ。これでは永遠に送れない。しかし、どうすれば良いのだろう。頭の中が混乱する。何か根本的な間違いがあるのかもしれないが、ロジック的には一度mainの初期化のところでエンドポイントにデータを書き込む呼び水のようなダミー処理をすれば良いのではないか。そうすれば次々に割り込みが連続し、うまくいくのではないか。

 やってみた。やっほー、動いたぞ。ダブルバッファーの仮想UARTモニターが前と同じように動き始めた。転送速度を測る。ややや、2Mbpsだ。素晴らしく早い。1KB送るのに数msしかかかっていない。そりゃそうだ。バッファーに1バイトづつ送るだけで60kbps近くあったのだから、その64倍だったら3Mbps近くあっても、おかしくない。

 もちろんこの速度は、単に内部でUSBドライバーが受け取った時の速さで、実際にホスト(PC)との仮想UARTでの転送速度ではない。しかし少なくとも内部では安定的にメガビットのオーダーでデータが送れたことになる。

 肝心のデータ欠落をチェックするために、同じ文字でなく、"0123456789"の文字列を送ってみる。うむ、全く欠落はない。きれいに数列が画面上に並ぶ。1字の落ちもない。いやあ、至福の瞬間である。今までの暗い気持ちが吹き飛び、天下をとった気分になる(相当中毒が進んでいる)。

 しかし、ロジックとしては不満がある。今の状態は、データがなくてもエンドポイントに立て続けに書き込む処理が動いているはずだ。今は単なるモニタープログラムなので関係ないが、別のSmpvcd仕事をするときはCPUリソースを無駄に使っていることになり効率が悪い。

 というので、エンドポイントの割込みルーチンにデータがなければ処理をやめるようにし(割込みが止まる)、送信関数には、バッファーが何もないときのデータ送信では、ダミーのエンドポイント書き込みを入れるようにしたが、こいつはまた全く動かない。

やっと満足できるコードになった(5/31/09)
 速度が2MbpsまでになったUSB仮想UARTだが不満が残っている。呼び水方式で、USBのエンドポイントにデータを送るところまでは良かったが、これでは送信していないときも延々とUSBドライバーは0データを送り続ける。

 送信データがないときはこの繰り返しを止め、データが来たときに再開するロジックを色々考えて試してみるが、ことごとく失敗する。奇怪なことに、メインルーチンの初期化でダミーの書き込みをすると上手く行くのに、送信関数の中でやると先に行かない。

 この間の差は時間だけだ。余りやりたくなかったがタイマーを入れて調整することにした。しかし全く変わりがない。何か変だ。このタイマー(元々の雑誌のソースに入っていたもの)は

   Delay( int i) { while(i)  i--; }

という簡単なコードだが、iをいくら増やしても変わりがない。コンパイラーの最適化を疑ったが、i--は立派な処理だ。無効になるわけがない。それにこの関数は、前から使っていたはずだ。

 しかし、やっぱりおかしい。念のため、コマンドを新設してこいつの待ち時間をSysTickの時間で測ってみた。うひゃー、全部0で帰ってくる。何と言うことだ。コンパイラーがこのステップを取ってしまっているに違いない。

 AVRでやったように、ループにasm volatile("NOP");を入れる(これはアセンブラーコードでなくマクロだそうだ。従ってARMでも共通)。ちゃんと待ち時間遅れが作れた。やっぱりコンパイラーの仕業だ。 雑誌で動いていたのは開発環境IARとGNUの違いだろう。それにしても、i-- がどうして無駄なコードなのだ。理解に苦しむが文句を言っても始まらない。

 ところが、待ち時間を作ってもうまく行くときと行かないときがある。時間待ちはあくまでも対症療法だ。やはり基本から確実な方法を探すしかない。もういちどソースコードをひとつひとつ追いかけて手順を考えることにした。Beale

 BeagleBoardのセットアップ(次記事で紹介)で少し日をあけたのが良かったのだろう。良い方法を思いついた。これまで送信関数の方ばかりに注目して、何とかしようとあれこれ考えていた。しかし、割込みルーチン側で動作モードを設定していけばうまく行くことに気がついた。そうなのだ。送信関数は、いつどこで割込みを受けるかわからないのでデータカウントが変わる可能性がある。バッファーを制御するスイッチにもうひとつ「データなし」というステイタスを追加してプログラムを組み直した。祈る気持ちでテストする。やった。前と変わりなくデータが送信できた。

 CPUのオーバーヘッドが明らかに減っている。その証拠に先のループで待つウェイトルーチンの時間が早くなったのだ。すごい。はっきりと差がわかる。時間にして3%くらい早くなっている。やっとまともなコードになったと思う。

 ソースコードの公開は迷った。単に大量送信の時間が表示されるだけの、このままでは実用性0(ゼロ)のモニタープログラムである。まあ、これをベースに色々アプリケーションを考えれば役に立たないわけでもない。がた老「AVR」研究所の記念すべき、初の「ARM」プログラムソースでもある。

 人のソースを流用させてもらっているが、殆どのソースは雑誌からなので問題ないだろう。STマイクロのデモプログラムも、ソースリストに「責任取らないからね」という文言しかないので問題ないと判断した。Makefile、リンカースクリプトとスタートアップルーチンはこちらのお世話になった。この場を借りて御礼申し上げたい。

 ソースファイル一式(ライブラリ、リンカースクリプト、Makfile)をここにおきます。Eclipseのプロジェクトファイルですが、Eclipseがなくても動きます。また、実行させるだけなら、STM_VCPDフォルダーの中のstm_vcpd.hexをDfuか、フラッシュローダーで書き込めば動きます。

「STMVCPD_archive.lzh」をダウンロード

 コンパイルの簡単な手順は以下の通り。

・コンパイラー(CodeSourcery G++)をここからダウンロードする。(OSはEABI、Sourcery G++ Lite 2009q1-161を選ぶ。 5/31/09現在)
・解凍したフォルダの下のSTM_VCPDフォルダーにカレントディレクトリを置き、DOS窓でコンパイル(make all)する。 FWLibや、USBLibのディレクトリの位置は変えないこと。換える場合は、Makefileを修正する。

・また、gccの標準ライブラリとヘッダーファイルは、gccの入っているbinフォルダーと同列のarm-none-eabiフォルダーの中のlib\thumb2下のライブラリと、include下のヘッダーを使っている。正確にはMakefileを参照。

・解凍ファイルの中のFWLibや、USBLibはV1.0で、現在のV3と混在させると動かない可能性がある。
・出来上がったhexファイルをDfuか、フラッシュローダーでファームに書き込む。
・STM32の電源を入れ、PC側の端末プログラムでUSBのVCPに接続し、何かキーを入力すると、WelComeメッセージが出る。

| | コメント (3) | トラックバック (0)

2009年5月28日 (木)

SysTickを使ったSTM32のUSB仮想UARTの速度測定

転送速度を測ろうとはじめたタイマーの設定に難航する(5/22/09)
 RTC(リアルタイムクロック)のプロジェクトの前に、もう少し仮想UARTモニターをまともなものにしようと色々考えている。週2日出ている事務所の往復がこういうロジックをまとめる格好の時間だ。

 今のプログラムの送信データ量はパケット1個あたり、わずか1バイトだ。USBの送信ポーリング周期を1msとすると、ボーレートは8kbpsしかいかない。今はキーボードからテストメッセージを出しているだけだからこれでも良いが、SDカードあたりのテストでは、少々遅すぎる気がする。

 ダブルバッファーにすれば、理論上では、エンドポイントのパケットバッファーが64バイトあるので、64×8×1000、512kbpsまでスピードを速めることが出来る。これならUARTの最速460kbpsでも楽々だ。やりかたはそう難しくない。バッファーを2つ作って、セマフォーのようなフラグを立て、空いている方へデータを移動させればよい。バッファーが満杯になれば、そこが0になるのを待つだけである。ついでにインターバルタイマーを入れて経過時間を表示するようにすれば改良の成果が良く分かるし、タイマーの勉強にもなる。これは面白そうだ。当面の目標をこれに決めた。

 そこで、STM32のタイマーを詳しく調べ始めたが、これがAVRと違って設定がとんでもなく大変である。高機能タイマーでなく、汎用のタイマーでも設定するレジスターの数は、数えてみたら何と20個もある。こちらはPWMのような複雑なことをやるわけでなく単純なインタバルタイマーが欲しいだけなのだが、これでは、まともに設定するまでどれだけ時間がかかることやら見当がつかない。どこかの応用例を見て組んだほうが早そうだ。Stm32

 タイマーなら、最初のテストに使った雑誌(DWM2008/6)のGNUサンプルソースにもあり、10ms単位で時間が測れる。しかし、こちらはSysTickを使ったタイマーで、ここでの設定はレジスターを直打ちで定義しているため、現在のソースに簡単には組み込めない。SystickはCPUの根幹部分であり下手に設定を変えると全く動かなくなる恐れがある。これも容易な作業ではない。

 どちらも壁が高いので、とりあえずは今動いている仮想UARTモニターから、不要なコードを取ってスリムにし、追加開発を楽にしようとした。ところが、これも結構難しいのである。もともとこのコード(蛙がピョン)はSTマイクロのVCP(Virtual COM Port)デモプログラムをベースにしている。ADCやDMAはそう問題なく削除できたが、UARTの関数群がはずせない。仮想UARTと言っても、外にだすわけではない。モニターの内部でUSBとの仮想UARTの入出力をするだけだから、外部のUARTは全く不要なのだが、これが微妙にUSBルーチンとからんで、取りすぎるとコンパイルエラーになったり、暴走したりする。

sprintfの不具合解消。リンカースクリプトの不整合だった(5/24/09)
 少しづつコードは減ってきたのだが、そのうち、仮想UARTモニターが途中でリセットがかかるようになってしまった。最初は、データを出力した直後一回リセットされるだけで、そのあとは問題なかったのだが、コードを減らしていくうち、遂に出力も出さずハングアップしてしまう。

 どうも、以前AVRで経験したスタックがデータをつぶしていく不具合に似ている。プログラムサイズをかえるとトラブルが変化するというのは、こういうときの典型的な現象だ。sprintfの実行で暴走するようなので、sprintfを再びコメントアウトするとOKとなった。やっぱりここが原因だ。うーむ、ヒープ開始アドレスがうまく伝わっていない感じである(ハングとは関係ないがsprintfをとるとフラッシュサイズは37 KBから11KBまで劇的に下がった。そうかGNUではこのへんがタコなのだなと納得)。

 良くわからないがマップファイルを調べる。ARMのマップファイルはAVRのnmコマンドと同じくらいの情報量があり(恐らく同じコマンド)、何とか書いてあることがわかる。ヒープアドレスを示す_endも載っている。あれえ、このアドレスがmain.cのSRAM変数の最初をさしている。このままではもろにかぶるはずだ。おかしい。

 暴走の原因を確認するため、とりあえずはヒープのスタートアドレスをmain.cの変数が終わったところのアドレスに、マップファイルを参考に決め打ちし、sprintfを入れてテストしてみた。おおお、うまくいった。リセットもせず快調にsprintfが動く。

 やっぱり、データのかぶりだった。しかし、何故、_endが正しくエリアの最後を指さないのだろう。今まで敬遠していたリンカースクリプトの勉強が必要になってきた。ウェブで調べ始める。このあたりはコンピューターシステムの専門分野でも一番奥の技術に相当ししかも機種依存が大きく、メーカーの技術者でもここに詳しい人は滅多にいなかった。

 昔はほとんど情報が外に出ない部分だったが、さすがはGNUである。沢山情報がある。ありがたい時代になったものだ。おおよその文法がわかったので、ウェブから拝借してきたリンカースクリプトファイル、memory.defを調べる。

 もういちど、マップファイルにもどって中身を見てみる。おや、COMMONというセクションがあり、これらがすべて.bssのあとに割り付けられている。これはmain.cの変数だ。

 おやおや、COMMONは、リンカースクリプトの.bssの範囲に入れないと全部外に出されてしまう。なんだやり方が書いてあるではないか。オブジェクトファイルかリンカーオプションの宣言の不一致だ。COMMONを.bssの中に入れなおす。

  .bss : {
        . = ALIGN(4);
        _sbss = .;
        *(.bss)
        *(COMMON)      /* ここを追加する  5/24/09 */
        . = ALIGN(4);
        _ebss = .;
    } > RAM          

 コンパイルする。やった。きれいに最終アドレスが_endに入った(sprintfで_endを表示させて確認)。やっとリンカーの仕組みもわかってきた。いやあ、組み込み系は奥が深い。30年前にやっていた大型機のオンラインシステムのシステム生成(シスジェンと言っていた)の経験が役に立つとは。この経験があったから、リンカースクリプトもそれほど恐怖感なく眺められたが、経験のない人にとっては、恐らく記号の密林に立ちすくむばかりだろう。ここはやはりかなり特殊な世界だ。_endj

 いつになく気分が良い。今度のトラブルシューティングは、昼なお暗いジャングルか真っ暗闇の洞窟のアドベンチャーゲームで、何か動いたのであてずっぽうに撃ったライフルの弾が見事に怪獣に命中したのと同じような気分だが、それでも全く偶然ではない。仮説にもとづいて手順を考え、その結果トラブルが解消したときは、どんなささいなことでも格別良い気分である。嬉しいことにもうひとつの不具合も解消した。

 NOP_Process( )がないとハングする原因は、「ねむい」さんからコメントがあり、コンパイラーの最適化のやりすぎではとの指摘があった。これまでテストできなかったが、ついでなので指摘どおり、外部参照宣言(extern)にもvolatileをつけてコンパイルしてみた。結果はその通りでどちらのNOPも必要なく、プログラムは問題なく動いた。変数宣言の方にはvolatileをつけていたが、externにまで必要とは思わなかった。

1バイト送信で57kbpsも出ていることがわかる(5/27/09)
 タイマーの勉強はなかなか進まない。8ビットのAVRのときは楽だった。単純な8ビットタイマーのオーバーフローから始めて自然に複雑なコンペアレジスターを使ったPWM制御まで理解できたが、いきなり10個以上のレジスターを前にして、さあ設定しろと言われても簡単にできるわけがない。32ビットプロセッサーは明らかに初心者向けではない。付録基板のついた雑誌には季節的に良く初心者向け特集などと銘打ってあるが、これは明らかに誤りだ。

 本当に初心者向けに基板を付録にするなら8ビットプロセッサーでないと無理だと思う。もっともこれでは基板に魅力がなくなり売れないのだろうけれど、32ビットプロセッサーの付録基板で、向学心に燃えた初心者が、途方もない壁にはばまれてどれだけたくさん挫折しているかと思うと心が痛む。ステップを踏みさえすれば、そう難しいものではないのに。

 それにしても、良いお手本が見つからない。見つかってもレジスターを直打ちで設定しているソースコードなので、STマイクロのデモソースベースのコードで動くか自信がない。SysTickを使ったタイマーの方が簡単そうなので、STマイクロのハードマニュアルや、ライブラリのSystick.cのソースを調べるが、ソースはいつもの長ったらしい変数の山で全くイメージがつかめない。マニュアルはOSのTick割り込みを意識した書きかたでこれも良くわからない。

 それでも収穫はあった。SysTickはシステムクロックとは独立したリソースで、Tickをだすタイミングを設定するレジスターは根幹部分のクロックリソースとは独立しているということである。そうなると、このあいだのGNUサンプルのSysTickを使ったタイマーが使えそうだ。

 定義を仔細にみていくと、SysTick関係の定義部分だけ持ち出せば、他に影響がなさそうだ。始め関係があると思ったのは、システムクロックの変数が大量に使われていたためだが、よく読むと、これは単に参照しているだけで本体とは関係ないことがわかった。

 まあ、何かがこわれるわけではない。SysTickハンドラーの割り込み先は、デモソースの中に既に定義済みだ。ここにカウンターを入れて、GNUサンプルの定義部分を慎重にとりだし、適当なテキスト表示の前後にタイマーステートメントをはさむ。

 動かしてみた。最初は0としか表示されなかったが、設定を変えると、1という数字が表示された。おお、動いている。少しづつ設定を調整して、それらしい時間がでるようになった。sprintfを直しておいて良かった。プロンプトの前にmsで時間を表示するモニターが動き始めた。リターンキーを打つ間隔がこれで測れる。

 雑誌では10msのTickということで、定義を調整し(それらしい定数を10倍した)、1msにしたが、どうも少し早い。ストップウォッチで時間を測る。1秒で、1500位のTickだ。さらに調整して1msのTickにする。いよいよ転送速度の測定だ。Photo

 おやあ、想定した8kbpsよりもっと早い転送速度だ。56kbpsは出ている。何度か、計算式を確かめる。間違いない。USBの外への転送ポーリングは1msだが、中はもっと早いタイミングなようだ。少なくとも8倍近く早い。そうか、STマイクロのVCPデモプログラムがV3でも改善されていないのはこのへんまでは破綻をしないためだ。これは今度のダブルバッファーの実装は楽しみになってきた。115bpsや、230kbpsでも動くVCPは喜ばれるはずだ。

| | コメント (0) | トラックバック (0)

2009年5月22日 (金)

JTAGは気難しい。恐れていた事態が現実になる

 Eclipseの環境が出来て一息入れたのも束の間、がた老AVR研究所は、次々に事件、出来事が発生し、その対応に追われて仕事どころ(あ、いや、一応、まだ週2日程仕事しています)ではない。

BeagleBoardが届いた(5/14/09)A5141832
 4/29に発注して、連休中毎日のようにDigiKeyのサイトをチェックしていたが、注文受理から、なかなか発送のステイタスに変わらずイライラしていた。アメリカも連休だったのだろうか。しかし、11日にステイタスが出荷済みになってからは早かった。何と2日で配達されてきた。13日は家人が不在で、今日14日に無事手元に届いた。電話で用途を聞かれたりするそうだが、全くそれらしいことはなし。ハンコを持って受け取りに行ったら、ポータブル端末のスタイラスペンを渡されてサインを求められる。さすが海外便だ。A5141833

 受け取ると、中身が入っているのかと疑うほど軽い。初の海外からの通信販売品である。記念写真をとる。充填材の中から可愛い箱が出てきて、いよいよあこがれのBeagleBoardとのご対面。電源アダプターには親切に5Vの表示ラベルが張ってある。モジュラージャックだと思っていたソケットはビデオのS端子だった。え、Sケーブルでも良いの?

 がた老AVR研究所のハイエA5141834ンドマシンである。このあいだ8 ビットプロセッサーから32ビットにいきなりあがって大変だったが、今度も大飛躍である。CPUチップはARM一族のハイエンドから2番目のARM CortexA8(ARM11の後継)コアとDSP、ビデオコントローラーを内蔵し、RAMがRevBの128MBからRevCでは256MBと増えている。クロックは600Mhzと一昔前のパソコンのスペックに近い。これが7センチ四方のボードに納まっている。

 気をつけなければならないのは、アプリケーションがどんどんパソコンに近づいていくことである。省電力、ファンレスだといくら威張ってみても所詮はローエンドのPCにも負ける。PCと同じような機能を開発してみても始まらない。本当の用途、最終目標が何なのかをよーく考えておかないと何をしているのかわからなくなる。パソコンで出来ることを何を苦労して作っているの?と笑われるのがオチである。

 接続に必要なケーブルで入手が難しいと言われる、USB-Aメス--ミニBオスのケーブルとHDMI--DVI-Dケーブル(これは入手難というより市販品が金メッキなどで異常に高い)は¥680と、¥1300でアマゾンで発注済である。とりあえず動かすのに必要な部品は、シリアルDSUB9ピンコネクターとボードのシリアルピンに接続するケーブルだけとなった。A5141838

 具体的なアプリケーションはまだ全く決まっていない。折角AVインタフェースが充実しているので動画関係に使いたいところだが、直接の用途が思いつかない。Linuxを入れてUSB経由のLANとHDDをつけ、とりあえずはディスクサーバーのようなことをやってみようかと思っている。まあ、これも少し先の話だ。DigiKeyでは私が買った数日後、案の定、在庫が0になって売り切れた。ひそかにほくそえんでいたのだが、昨日見たら在庫が25に戻っていた。何だ。次のロットは遅れるなどと言っていたのは誰だ。少々あせりすぎたかもしれない。しかし所有欲だけは十分満たされた。しばらくは棚に飾って喜んでいよう。

やっとフラッシュにJTAGのOCDコマンドでイメージが書き込めた(5/17/09)
 BeagleBoardはさておき、ARMの開発である。次の目標はRTCと決めてあるが、それまでに片付けておきたいことが沢山ある。GDBによるソースコードデバッグは余り深入りするつもりはない。USBやシリアルなどタイムディペンドな機能の開発ではプログラムを途中でブレークすると動作状況が変わってデバッグにならなくなる。恐らくSDカードのアクセスも同じだ。

 ハングアップしたときなどは威力を発揮すると思うが全体がまだわかっていないので使いこなせるかどうか。それにフラッシュ上ではブレークポイントが限られており、自在に止めるにはSRAM上にコードを移す必要がある。しかしSTM32はSRAMが20KBしかないので今のプログラム(既に38KBもある。もっとスリムに出来ると思うがこれも未着手)でも、もう移動不能である。

 で、やろうとしていることはピンを切り替えたり、リセットすることなしに、Eclipseの下でプログラムが書き込め、そのままテストに入れる環境を作ることである。Eclipseにこだわるのは、ここの豊富なソースコードの編集・検索機能だ。表示されているマクロステートメントにカーソルを当てるだけでプロジェクトの中の定義元を調べてマクロを展開してくれるし、外部変数や関数の所在も一発でわかる。沢山のモジュールで構成されるプロダクトではありがたい機能だ。まだ他にも沢山機能があるらしいが調べ切れていない。

ファーム書き込みのスクリプトを作る前に、コマンド入力で、フラッシュ書き込みのテストをする。要は、プロテクトをoffにし、フラッシュを消去し、書き込むと良いはずなのだが、これがこの前に書いたようにとても難渋した。

バンク、セクター、アドレス、オフセットの設定が難しい。まずバンクである。こういうJTAGのような組み込み系ではいくつもあるのが常識なのだろうが、こちらはAll in oneのワンチップコンピューターの世界しか知らない。コマンドにバンク番号を必ず入れるのがなかなか慣れない。

 バンクが常時0なのは良いとして、セクターの数え方が難しい。STM32では消去の単位がセクターではなく独自のサイズを持っており、4セクター単位にきっちりスタートとエンドを入れないと言う事を聞いてくれない。

 アドレスもそうだ。コマンドの指定するスタートアドレスは、0から始まる相対アドレスなのか、実際にメモリマップしたあとの絶対アドレスなのか、コマンドによって違うような気がする。

 flash write_image ファイル名 <offset> というコマンドのoffsetも良くわからない。ファイルの種類によって違うような気がする。.binファイルなら良いが、elf、hexのような絶対アドレスが内容に指定されているイメージファイルはどうなるんだろう。offsetされるとそれもずれるのだろうか。いや、わからないことだらけである。

困ったときのGoogle頼みだが、的確な情報がない。仕方なく少しづつ実際に確かめて進めるしかない。アドレスを間違えても大丈夫なように、フラッシュの後半のアドレスに狙いをさだめて、コマンドを確かめてみる。

 何度か怒られながら、0xE000のフラッシュエリアに1KB余りのbinファイルを書きこみ、消去するまでの過程を実現するのに成功した。

flash erase_sector  0 46 49                            セクター4KB単位に消去(必ず4K単位)
flash write_image  XXXX.bin 0x800E000  bin     設定アドレスからファイル書き込み
flash  erase_ check  0                   バンク0のフラッシュのerase状態の表示Ocd

以上のコマンドの投入で、0x0800E000のセクターがnot erasedになり書き込まれたことが確認できた。このあと、mdw  0x0800E000  256などで、書き込まれた内容を確認する。
さらに、同じflash erase_sectorをかけて再び内容が 0xFFFF…..になっていることを見る。やっとのことで、Eclipseのフラッシュスクリプトを作る目処がたった。

突然JTAGがR/Wエラーでおかしくなる(5/19/09)
 残るは、いよいよEclipseでのフラッシュ消去、書き込みのコマンドスクリプトの作成である。フラッシュを全て消すのでなく、0x3000以降だけを消去するコマンドを作る。OCDのフラッシュコマンドの基本はセクター単位(1KB )で消去の単位は4KBなので、flash erase_sector 0 XX  YYとして、XXを4、YYを127でよいはずである。このあとはアドレスは考慮しなくて良い(はず)。というよりGDBでロードするから、このコマンドはいらない。

 スクリプトにする前に手動でやってみる。ところが、さっきまで動いていたflash erase_sector が言うことを聞いてくれない。何回かやるうちに何とか書き込むべきアドレス0x08003000以降がerasedになったので、flash write_imageでelfファイルを書き込んでみた。ちゃんと書かれたか、flash erase_check 0 で確かめる。

 おやあ、Dfuが書き残してerasedになっていた、0x08002000から3000までのセクターもnot erasedになってしまっている。不吉な予感がよぎる。Eclipseを止めてJTAGをはずし、基板だけで動かす。全く動かない。不安が高まる。動作モードをDfuに変え、再立ち上げ。うわあDfuSeが基板を認識しない。やってしまった。Dfuを上書きしてしまったようだ。

 JTAGを接続しなおし、DOS窓でOpenOCDを立ち上げフラッシュの状況を見ようとした。これがBlock Read Errorのメッセージで見ることすら出来ない。当然、さっき動いたflash write_imageもエラーリターンする。えらい事になってしまった。予想されていた最悪の事態だ。だいたいflash probe 0というフラッシュの全体状況を表示するコマンドも、サイズはわからないけれど、だいたい128Kくらいかなあ、などという頼りない返事が返ってくる。

 こわしてしまったのだろうか。現象はハードエラーのような感じだ。なるべく冷静になって状況を確認する。JTAGはいわばコンピューターの心臓部に直接、検査針をつっこんで制御しているようなところがある。しかし、コマンドで動かしている限り、ハード的に装置をこわしてしまうようなことはないはずだ。ファームに何かを書いたためにCPUが暴走し、JTAGが正しい結果を返せないと考えるのが妥当だろう(そう思いたい)。

 そういえば、前のLPC2388で何もプログラムが入っていない状態では、JTAGでファームに書くことが出来なかった。そうだそれに違いない。気分が少し明るくなった。何か動くプログラムを書き込めば良いはずだ。しかし、Dfuは消えてしまったし、JTAGはこんな状態だ。

 このあいだ「ねむい」さんのコメントを見て、「十分注意しているから、こんな事態にはなるまい」とたかをくくっていた事態が急に現実になり苦笑いである。第三の方法、ROMブートローダーの出番である。この方法があるのは知っていたし、UART1はこの前のGNUサンプルを動かすときに配線済みだが、実際の手順は「ねむい」さんの記事が大変役に立った。「ねむい」さんありがとう。

 手順が決まっていれば後は作業だけである。BOOT0をHighにするピンヘッダーを立て、STマイクロからPC側のダウンローダーを落とし、UART1を秋月のUSB-UARTアダプターとつなぐ。うむ、STM32を認識した。何、フラッシュが全部プロテクトされているぞ。これが原因だったのか。どうせなら、Dfuを復元してやろう。「ねむい」さんのところからDfuのhexファイルを頂きファームに焼きこむ。よーし。USBをつなぐとPCが反応し、DfuSeがSTM32を認識した。A5221938_2

 これでJTAGが動けば、完全に元に戻ったことになる。あせる気持ちを抑えJTAGケーブルを基板に接続し、OpenOCDを立ち上げる。Telnetを開きコマンドを入れる。万歳!これまでのおかしなレスポンスは全くなく正常な状態に戻った。

 やれやれJTAGは気難しい。Block R/Wエラーが頻発しプロテクトの状態がコマンドを入れるたびにおかしな状況になるのは、ターゲットのCPUが暴走していたからに違いない。しかし逆に言うと、CPUを暴走させてしまうとJTAGが動かない状況に簡単になってしまうということだ。これはやっぱり相当経験を積んでからでないと使いこなせないツールのようだ。

| | コメント (0) | トラックバック (0)

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を入れたほうが良いかもしれない。夢がふくらむ。

| | コメント (4) | トラックバック (0)

2009年5月 8日 (金)

STM32のUSB仮想UARTモニター遂に完成

 今年の連休は殆ど外に出かけず、いわゆるCQ-STARMと呼ばれるDWM2008年5月号の付録基板、STM32F103をGNUベースで開発するプロジェクトに没頭していた。こんなに夢中になったのも久しぶりである。やっとのことでUSBの仮想COMポートが実用レベルの域に達した。PCから簡易モニターが開けるのでUARTを通じて開発を進めることが出来る。いやあ今度も大冒険だった。

仮想UARTからの送信データが抜ける(5/4/09)
 STM32のUSB仮想UARTは、とりあえず送受信は出来るようになった。しかし、この雑誌のファーム(蛙がピョン)が使っているUSBへの送信関数は不安定極まりない。特に、連続して送ると前のメッセージを無視して最後の送信メッセージしかPCに届かない。

 受信は出来ているようなので1文字単位のエコーバックは出来るが、ARM側からの連続した送信は全く駄目である。それに受信に関しては不審なことがある。この前、書いたようにデバッグ用に用意されている2文字のコマンドがCD-ROMに入っていたオリジナルのファームに戻してみても、全く機能していないことである。どうもおかしい。

 ソースコードを調べて行ってその原因がわかった。メインループの中で受信バッファーにデータがあるかどうかをバッファーのデータサイズ変数(count_out)で聞いている。受信バッファーは、USBの受信エンドポイントから直接移しているだけでキューイングなどはやっていない。しかもこの変数、count_outは、このループの最後でクリアされている。キーボードの入力はどんなに早くても1/10秒単位である。これでは2文字のデータがUSBのエンドポイントのバッファーに揃うことは絶対にありえない。

 送信がおかしいのは、恐らく送信バッファーで、まだ送っていない前のデータを新しいデータで塗りつぶしているからであろう。USBはホスト(PC側)が完全な主導権を握っており、UARTのときは、ディバイス(ARM)側から送信は、ホストのVCPドライバーからのポーリングで送信するはずで確か、最小でも1ms間隔だったと記憶している。バッファーから正しくデータが送られてバッファーが空にならない限り、次のデータは送れないはずだが、このコードはそういう制御は何もしていない。

 受信の方の不備といい、送信のところといい、どうもこのソースコードの作者は、USBが非同期で沢山のバッファーを通して動いていることを理解しているか疑わしい。困ったことになった。お手本が頼りにならない。加速度センサーのADコンバータが既に動いているし、これをベースにアプリが広げられるという最初の期待はもろくも裏切られた。

 確かにキーボードから「*」の入力で連続した加速度センサーの数値を表示することには成功している。しかし、これは加速度センサーの表示タイミングがUSBの送信間隔よりはるかに遅く、せいぜい10msに一回程度だから、たまたまボロが出なかっただけである。これはオリジナルのSTマイクロのVCPソースからじっくり調べる必要がある。

sprintfは動いたぞ(5/5/09)
 こどもの日の今日は雨。晴れのときは何となく落ち着かないが、雨のときは心置きなくARMマイコンと過ごすことが出来る。このところARMの話題ばかりで、がた老AVR研究所と名前をつけた手前、AVRのことを期待して来られる読者には申し訳ないが、アクセスログを見ていると殆どの読者はキーワード検索で来られるようだ。余り気にすることはないのかもしれない。Sbrk

 それはともかく、何とか動かすためにこのあいだコメントアウトしたsprintfである。書式付の出力関数は、フラッシュが大きくなっているので気楽に使えるし、今後のデバッグの生産性のためにも生き返らせたい。仮想UARTの不具合究明を少しお休みし、こちらの方をやってみることにした。

 まず、この前のウェブの情報には、問題の_sbrkのミニマムコードが掲載されている。真面目にコードを読んでいく。何だ、そんなに難しいことはやっていない。ヒープアドレスのエントリーを要求に応じて上げているだけだ。その間が確保したメモリというわけだ。メモリの解放は考える必要はない。スタックと被るとエラーを出すようになっているが、これも今のところいらないだろう。

 _endという外部変数が気になったが、リンカーが設定するというコメントを信じてソースを追加しコンパイルしてみた。おおー、NO ERRORである。調子に乗って、オリジナルソースのsprintfのコメントの部分をはずしビルドする。これも問題ない。いよいよテストだ。「*」を入れる。やった。やりました。加速度センサーの数字が見事に出力された。オリジナルと全く同じ機能が、GNUベースで実現した。

 STM32で、GNUの標準ライブラリが使えないというのは、このあたりに原因があるのかも知れない。私の場合、リンクエラーが出たので顕在化したが、どこかのライブラリの中でもし何もしない_sbrkのスタブルーチンが用意されてしまっていると動かないことになる。

仮想UARTは本家のSTマイクロのサイトでも紛糾(5/6/09)
 お手本にしようとした雑誌の内蔵ファーム(蛙がピョン)の応用をあきらめて、もとのSTマイクロのVirtualComPort(以後VCP)のデモプログラムで仮想UARTの実装を始めた。内蔵ファームの仮想UARTの部分は、このVCPのソースを殆どそっくり利用していたので、理解が早い。送信バッファーの取り扱いがわかった。最初から書き込まず、足しこんでいる。そうか、これなら内蔵ファームのようにデータは失われない。

 その内蔵ファームについて前回の記事では、その後の情報収集で少し誤解があったようなので訂正しておきたい。2文字コマンドは絶対動かないと書いたのだが、これはGainerプロジェクトの仕様なのだそうだ。キーボードでなく、別のマシンからの入力を想定しているのでバグではない。キーボードから入れるときは、端末プログラムで入力コマンドをカット&ペーストすると動くと言う。

 実際に試してみて動くことを確認した。情報源のサイトでは「変な仕様だなあ」などのコメントがついていたが、同誌の次号6月号3章の記事を読み直して少し謎がとけた。この記事の中で、コマンドがすべてASCIIなのに端末側にわざわざフリーウエアのAcknowrich(アクノリッチ)を要求している理由が全くわからなかったのだが、こういうことだったのである。それなら最初から、そう書いてくれれば混乱することはなかったし、アクノリッチを使うこともなかったように思うのだが。

 それはさておき、STマイクロのVCPデモソースの解析の方である。ここではmain.cとhwconfig.cで、USBの受信バッファーのデータサイズ(count_out)分をUARTへ送り、UARTからのデータは、UARTの受信割込みの度に、USBの送信バッファーに書き足している。USBの送信バッファーはエンドポイントの割込みを処理するusb_endp.cで定期的にハードのパケットレジスターに送信バッファーサイズ(count_in)だけ書き込まれる。いずれも処理のあとにバッファーサイズの値は0にリセットされる。

 問題なさそうである。これを元に鼻歌まじりで、1文字送受信関数、USB_putc、USB_getcを作り、USB_putcを使って、文字列用のUSB_putlineまで用意して、仮想UART超簡易モニターを実装した。STM32の開発ベースになるものである。とりあえずは、入力をエコーバックし、リターンキーでこれまでのデータを送出、0、1、でLEDのOFF/ONという仕様だ。ファームを書き換え、意気揚々とテストに入る。

 と、これが言うことをきかないのである。受信は問題ないが、ホストへの送信が前と同じようにうまくいかない。一文字なら良いが(エコーバックは完全だ)、一気に送るとデータ落ちが激しい。それにおかしなことにデバッグ用のLEDをONするステートメントをメインループからはずすとハングする。???である。

 おかしいな。送信バッファーは64バイトもある。いくら実際のUARTよりはるかに早いタイミングでプログラムからバッファーを書き換えても、USBの割込みが入ってハードのエンドポイントレジスターに書き込むときは、正しいバッファーの内容と、そのサイズを示しているはずだ。現象はあきらかに書き足す処理の時に割込みが入って、サイズとバッファーの内容との不整合が起きているとしか考えられない。バッファー転送とサイズ変更の間で割り込まれないようにしておく必要がある。

 しかし、STM32で割込み禁止をかける方法がわからない。8ビットのAVRと違ってSTM32 の割込み環境は目茶目茶複雑だ。下手にかけると他がおかしくなる。それにLEDのステートメントがないとハングアップするというのも奇怪な話である。

 USBの知識も生半可なので少し勉強し直し、色々いじってみたが改善しない。うーむ、よくわからない。思い余って、このあいだ試して味をしめた生のステートメントをGoogleに投げる方法をやってみた。キーワードは、ユーザーバッファーから実際のエンドポイントにデータを移すSTマイクロ提供のライブラリ関数、UserToPMABufferCopy(...)である。Pmabuf

 すると、また当たったのである。こんどもSTマイクロのフォーラムだ。それも私と全く同じ仮想UARTのデータ抜けで困っている人たちの議論である。3ページ分ある。英語の斜め読みなので、完全に理解したとは言い難いが、UARTが低速のときはUSBがパケットを送るタイミングとぶつからないが、高速になると取りこぼすバグの対処の議論である。

 色々な改善案の出し合いがあって、最終的には、一方がsystickを使った新しいコードを提案してスレッドは終わっている。しかし、このコードはのちほど本人が否定して、問題は解決されていない。STマイクロの対応(発言)はない。去年(2008年4月)の話なのでソースはV1.0ベースだ。これを受けて次のバージョン(V2)でどうなったか、USBライブラリをダウンロードしてみたが、何も変わっていなかった。ただこれはこの関数UserToPMABufferCopyだけの問題ではない。V3のVCPのデモソースは見つけられなかった。

 さて、どうするか、である。割込みを止めようとウェブを探し回ったら、何とユーザーモードでは割込みをペンディングできないことがわかった。うーむ、やっぱり32ビットプロセッサーは難しい。LEDを動かさないと何も動かずハングするとか、count_outなどの外部変数を監視していても変化しないとか、まだわからないことだらけだ。

NOP_PROCESS()ですべてが解決した(5/8/09)
 AVRだと気楽に割込みを止めてアトミックオペレーションに備えることが出来るが、ARMあたりはRTOS(リアルタイムOS)を意識しているので、そう簡単にユーザーレベルで割込みを止められたら確かにおかしくなることはわかる。ただ、今の現象はあきらかに、USBのエンドポイントの送出割込みがバッファー転送中に起きていると思われる現象だ。

  向こうが待ってくれないなら、こちらで待つ(バッファーが0になるのを待つ)ようにしようとしたが、これも出来ない。モニターに使うUARTだから早さは求めない。バッファーサイズが0になるのを待って、1バイトづつ送っても問題ないのだが、whileループで、これを調べても変化しない。ここでループしたままになる。ユーザープログラムからこのバッファーサイズ(正確には変化)が見えないのである。

 別のお手本を探すしかないかと、あきらめ気分になっていたとき、STマイクロのソースを見ていてふと目に留まったものがある。何かのフラグを調べているプロセスでwhileのあとの処理クローズにNOP_Process()という関数が入っている。これは何だろう。コンパイラーの最適オプションでおかしくなるのをさけるためなら、インラインアセンブラのasm("nop")で良いのに何故わざわざ別の関数を呼んでいるのだろう。

 頭の中に何か灯りがともった。何かにおう。これが長年この世界にいた勘かもしれない。もしかしたらもしかするかもしれない。エンドポイントにデータを送る関数USB_Putc()でbuffer_outが0になるまで、このNOP_Process()で待ってみることにしてみた。バッファーを送った直後なら、次のデータ転送の時に割り込まれる可能性は殆どない。ついでにはずすとハングするLEDのステートメントもこの関数にしてみる。だめもとである。あまり期待もせずテストしてみた。

 何と、何と、これが見事に機能したのである。長いメッセージも全くデータ落ちなく出力される。LEDプロセスがなくても問題なく動く。なぜ動くのか理由はわからない。ただ山勘でやってみたのがあたった。一回の転送タイミングで1バイトしか送れない(1msのタイミングで8kbps)が、今はこれで十分である。調整していけばもう少し早くなるだろう。Stm32monitor

 いやあ、嬉しい。世の中がばら色に見える。寝ている女房を起こして喜びを分かち合いたい気分である。STマイクロのフォーラムであれほど紛糾していたのだから、殆どあきらめていた。それが低速とは言え、モニタープログラムが問題なく動いた。鼻が高い。リターンキーで、貯めこんだメッセージを1字も抜けずに表示するし、LEDも0、1のキーで点滅する。満足、満足である。

 今のところ高速化は必要ないが、バッファーをリングバッファーにするか、バッファーを書き換えるのときにUSBの割込みをペンディングする方法が見つかれば、もっと高速に送れる。まあ、これは先の話である。それよりも次はJTAG環境を整備したい。Dfu経由だと一回の書き換えに25クリックもかかる。

| | コメント (2) | トラックバック (0)

2009年5月 4日 (月)

STM32基板のUSB仮想COMポートがGNUで動いた

LPC2388は少し休んでSTM32の方に専念する(4/27/09)
 LPC2388基板を付録にしたインターフェース誌の次号(6月号)が出たので買ってきた。chaNさんが本名で2章にわたって執筆されている。UARTやUSBホストの解説もある。うーむ、みんなやろうとしていたことばかりだ。何か急に道が広くなって歩きやすくなると同時に、生来のへそ曲がりが出て逆に何となく意欲が失せてしまった。

 昔からこうだ。みんなが進んでいく方向についていくのが嫌いで、違う方、変わった方に行きたがる。今度の号でも一番の情報は、LAN&SDカードソケット拡張基板のイーサネット物理層のトランシーバーICの型番がわかったことである。 LAN8187とある。Ws000000

 実は、今度のLPC2388はイーサネットの論理層(MAC層を含む)をサポートしていると知り、ネットでこの物理層のICを探していた。しかし目に付くのは殆どがギガビットイーサのICばかりで、10/100MあたりのICはDigiKeyで見ると流通在庫のない旧製品が多く1個からは売ってくれない。残念ながらLAN8187もDigiKeyでヒットしたが、販売最低個数は800ヶで手が出ない。

 そう、この別売りのLAN&SDカード拡張基板の自作を企んでいる。買えば¥6800だそうだが、今度も、いくら何でも「ぼったくり」だ。SDカードソケット、モジュラージャック(パルストランス付き)、AタイプUSBソケット(これは余計)を合わせても小売価格で\1000しない。それに物理層ICが\500前後としても部品代は¥2000以下、基板を起こす費用が1枚あたりそれくらいかかったとしても、売価がその倍というのはないだろう。秋月なら半分で売る。

 この前の雑誌付録のフリースケールのイーサネットマイコンのときもそうだった。別売りの部品セットの法外な価格に反発して、秋月のモジュラーを無理につけてピンを折り、パルストランスを外付けして動かした(2008/9/9の記事)。今度も恐らく誰かが私と同じようなことをしようとしているに違いない。データシートさえあればやっていることはそう難しくない。外付け部品は発振子だけで、あとは結線するだけだ。いずれ物理(PHY)層ICを手に入れて作ってやる。

 それはともかく、新しい号の雑誌で逆に関心の方向がLPC2388より、去年の雑誌付録STM32基板(Cortex-M3 STM32F103)の方に移ってしまった。32ビットプロセッサーと言ってもこの石は、Thumb2という16ビット命令でしか動かない廉価版だが、せっかくSDカードソケットをつけたのに活用していない。 それにこちらの方が情報が少なく難しそうである。へそ曲がりに加えて、例の中毒だ。出来ないこと、難しいことを克服したときの充実感がたまらない。いつのまにか険しい先の見えない脇道にそれてしまう。

STM32をGNU環境で開発する(4/29/09)
 STM32はこのあいだUARTが動いたが、これは普通のTTL-UARTで、USBを経由していない。このSTM32はUSBがついているのが特長だ。USBインターフェースの勉強のためにもUSBを通してPCとお話がしたい。

 しかしUSBを動かすには、複雑で面倒な設定が必要で自前で作るのは大変だ。ライブラリに頼って開発しないと効率が悪い。このライブラリ(USBLib)やデモプログラムは、雑誌のCD-ROMに他のペリフェラルのライブラリ(FWLib)とともに入っているが、これらのソースはIARやKeilの商用コンパイラーをプラットホームにしていて、GNU向けのソースではない。 仕様は殆ど変わらないはずだが、肝心のMakefileとリンカースクリプトがない。

 それでも、「STM32 gnu」で検索したら結構沢山のサイトが見つかった。探した中で一番簡単そうな、ここのサイトのMakefileとリンカースクリプトを拝借してコンパイルしてみることにした。お手本のソースは雑誌のデモ(蛙が跳ぶやつ)のファームウエアだ。知らなかったが、雑誌付録のCD-ROMにちゃんとソース一式が入っていた。

 しかし、このMakefileはこの前と比較にならないほど複雑でちょっと見ただけでは何をやっているのかよく分からない。ウェブ上のマニュアルと首っ引きで、やっとのことでWINARMからCodeSourcery G++の環境に移し、ソースのコンパイルまではうまくいくようになった。

 はじめはライブラリの構築がうまくいかず途方に暮れた。一部の$で囲まれる変数、$(CFILES)などが置き換わらず、Nullデータになってライブラリが作れない。お手本にしたMakefileはCygwinのUNIXベースのもので、こちらの環境はDOS窓だ。/ではなくて¥(バックスラッシュ)などのセバレータが入るとおかしくなるのかと思ったが、それが原因ではなかった。

 変数に入れるファイル名をひとつだけにするとうまくいったので、DOS窓の環境変数などのバッファーのオーバーフローかと、少しづつ増やしていった。ところが、いくら増やしてもエラーにならない。結局、元の全部を入れても相変わらず正常にライブラリが構築される。直ってしまったのである。???であるが、余り深く詮索するのはやめる。とにかくすべてのソースのコンパイルは、いくつかの警告メッセージがでるもののOKとなった。

 しかし喜んだのも束の間、リンカーで以下のようなメッセージをだして失敗する。f:/gcc/bin/../lib/gcc/arm-none-eabi/4.3.2/../../../../arm-none-eabi/lib\
libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text+0x18): undefined reference to `_sbrk'
f:/gcc/bin/../lib/gcc/arm-none-eabi/4.3.2/../../../../arm-none-eabi/lib\
libc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text+0x20): undefined reference to `_write'
f:/gcc/bin/../lib/gcc/arm-none-eabi/4.3.2/../../../../arm-none-eabi/lib\
libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text+0x18): undefined reference to `_close'

 これは標準Cライブラリの中のエラーだ。ヘッダーファイルと実際のシステムライブラリとがどうも不整合を起こしているようだ。うーむ、やっぱり駄目か。しかし、せっかくここまできてあと少しなのに残念だ。このあたりはビルドのなかでも一番難しいところでこれ以上は手が出ない。ライブラリのリンクではLinuxで散々苦労した。やっぱりウェブと同じWINARMに替えるしかないか。

 殆ど諦めたが、寝る前の最後に頼みのGoogleに、だめもとで上記のメッセージのうち環境に依存しない部分の
libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text+0x18): undefined reference to `_sbrk'
をぶちこんで検索してみた。すると何と該当するサイトが見つかったのである。

 STマイクロのサポートのページで全く同じメッセージを出して立ち往生している人の質問であった。幸いなことに回答が出ている。英語なので今ひとつはっきりしないが、要はsyscalls.cなどのOS用のルーチンを組み込まないでコンパイルすると、それ向けの関数がないのでエラーになる。 syscallを使っていないのならこのエントリのダミールーチン(stub)を作れば良いということである。

   言われるまま、ユーザー関数を入れている適当なファイルhw_config.cに、_sbrk _writeなどの関数を追加する(中ではなにもしない)。祈る気持ちでmakeする。おおお、NO ERRORだ。Makefileどおりelfファイルとhexファイルができた。勢い込んでDfuでファームを書き込む。動かしてみた。順調にVirtualComPortが認識され、LEDが点いた。よーし、動いたぞと、キーボードから入力する。残念。キーボードの反応はない。やれやれやっぱりまだ駄目か。まあ、ゆっくりデバッグしていこう。

遂にBeagle Board RevCを発注してしまった(4/30/09)Ws000001
 前から、目の前のプロジェクトが上手く行かないと新しいリソースに手を出す癖がある。素直に雑誌の環境でコンパイルすれば良いものを、わざわざ茨(いばら)の道を選んでGNUで苦闘している。こういうときが危ない。このあいだのイーサの物理層ICを探したときにDigiKeyに寄って、見るともなくBeagleBoardのページに行ったら、何と在庫が25に減っている。しかも価格は円高でこの前見た価格より\1000以上安い¥16,062だ。

 確かこの前は3桁の在庫があったはずだ。うむむ、こういうものは次のロットは遅れることが多い。よし買ってしまおう。7,500円以上なので2000円もする送料が無料だ。この際、色々な手に入りにくい小物を手に入れるチャンスでもある。フリースケールのイーサネットマイコンのモジュラーはすぐ思いついた。今度のイーサ物理層のICも買っておきたい。しかし、ひとつから買える適当なICがなかなか見つからない。

 買うとなると気がせいてきて、とうとうICが見つからぬまま29日の深夜、モジュラージャック2ヶと合わせて発注のクリックを押してしまった。代金は消費税を入れて¥17,700。いやあ、これで、がた老AVR研究所に遂にハイエンドの組み込みボードが来ることになった。暫くは気分が高揚して何も手がつかない。このあいだ6年乗った車を乗り換えたが、これほどの感動はなかった。

 恐らく品物が届いても、簡単にはすぐ手が出せないだろうが、可能性だけはやたらに広がった。FPGAと云い、趣味の世界でこれだけ興奮できるというのも幸せなことである。モニターをこいつのために新調する必要がある。ビデオ出力がデジタルだからだ。現在のメインモニターは、もう10年以上使っている古い17インチブラウン管モニターでディジタル端子などついていない。そのかわり今や珍しいケーブル5本のRGBコンポーネント端子がついている(接続はもうひとつのアナログ15ピンの方だが)。しかし目に優しく長く使っても疲れない。とても愛用している。このあと30万近く出して買ったナナオの液晶モニターにはDVI端子がついているが、これは娘にやってしまった。

 発注してしまってから、イーサ物理層ICのMicrel社のKSZ8721BLがDigiKeyで1個売りしているのが見つかった。0.5ミリピッチのLQFPで48ピン。変換基板で対応可能である。データシートも完全にある。価格は¥497。しかし、後の祭りである。

GNU環境でやっと仮想COMポートが動いた(5/3/09)
 STM32開発のその後の進展は、はかばかしくない。LEDの点灯までは動いたが、USBからのレスポンスは全くないままだ。PC側からはVirtualComPortとしてポートが見えるのでUSBの初期化はうまくいっていると思われるが、その後が進まない。

 ソースは「蛙がピョン」のオリジナルのままである。「*」を入れると3軸の加速度を表示するはずだが、全く表示しない。ソースの中にデバッグ用と見られるいくつかのコマンドがあるので(「?*」でバージョン表示、「Q*」でリセットなど)入れてみるが、それにも反応がない。main.cに手を入れて無条件でメッセージをUSBに出力するステートメントを加えたが、反応なし。どうもLEDを点灯したあと暴走している感じだ。

 ここでJTAGインターフェースが使えれば、もう言うことなしなのだが、デバッガーの設定はプロジェクト単位にする必要があり、今のところは全く手が出ない。たとえ入れても何をデバッグしているのかわからないだろう。頼みはやっぱりウェブによる先人たちの経験報告である。

 Makefileを貰ったサイトでは、動いているように書かれているが、同じWINARMを使って仮想UARTを動かそうとしているサイトではGNUでは動かないというレポートが多い。あるサイトで「STM32はThumb2命令で動くので、ARM命令で作った標準ライブラリは駄目」とあるのを見て、慌ててCodeSourceryのディレクトリチェーンから、それらしいライブラリパスを指定して(gcc/arm-none-eabi/libからgcc/arm-none-eabi/lib/thumb2)みるが、前と同じ。

 やっぱり、リンクエラーをなくすためにライブラリのスタブルーチンを入れたことが原因だろうか。それに関連して、断片的な記述で良くわからないが、sprintfを入れようとしてsyscalls.cを要求され開発をあきらめたというこの記事がどうも気にかかる。そういえばこのあいだのスタブルーチンの説明にも、syscallsを作るとか何かという話があったことを思い出した。

 念のため、ターゲットのコードを見てみる。何と、sprintfが加速度を表示するために使われているではないか。もしかしたらこれが原因かもしれない。もう一度、スタブルーチンを入れろと言った記事を詳しく読み直す。「sprintfは、一時メモリをmallocで取るので、これを使うときは、_sbrkだけはまともに書け」とあるではないか。これだ。_sbrkのエントリーは今度のダミールーチンに入っていて何もしていない。これに違いない。

 正しい作り方が良くわからないので、とりあえずこのsprintfの部分をコメントアウトしてmain.cを適当に作り替え(キー入力をループバック)、ビルドし直す。今度は少し動くような予感がする。hexファイルをdfuファイルに変換し(結構面倒だ)、Dfuローダーで書き込む。ピンを差し替え(早くJTAGにしよう)、USBソケットを抜き差しし(うーむ気があせる)、PCのTeraTermを起動させ、仮想COMポートを選ぶ。

 勘が見事に当たった。TeraTermからは文字化けしているが連続して文字が出てくる。思ったようには出力されていないが、始めて仮想COMポートが動いた瞬間だ。いやあ嬉しい。何度も書いているが、この快感がたまらない。いや、やっぱり相当中毒が進んでいるか。

 行末のNULLキャラクターを調整して、とりあえずキーボードからの入力を忠実にエコーバックする仮想端末が完成した。まだ、USBソケットを抜き差しすると端末がCOMポートを認めなくなったり、最初のウェルカムメッセージが想定どおり出ないなどの不具合は残っているが、これでSTM32の開発環境は大きく前進した。端末からターゲットの状況が手に取るようにわかるモニター機能は、これからの機能の開発には欠かせないからだ。

| | コメント (5) | トラックバック (0)

2009年4月26日 (日)

STM32基板にもJTAGインターフェース

薄紙をはがすように見えてくる(4/21/09)
 ARMプロセッサーの構造が少しづつ少しづつ理解できるようになってきた。これまでチンプンカンプンだった雑誌の記事が意味のあるものになってくる。GNUを使ったSTM32基板のプログラム開発の記事(DWM誌2008年6月号4章)など、最初は全く理解できなかったが、周辺の情報が増えたので少しづつ具体的なイメージが湧いて手順が見えるようになってきた。薄紙をはがすように全体が見えてくる。これはこれで楽しいものである。

 スタートアップルーチンが必須であることも、この記事にちゃんと書いてあった。スタートアップルーチンから、Cソースのmain.cにどうやって制御を渡すのかわからなかったが、ソースを調べると例外割込みベクターにあることがわかり、全体の流れがはっきりしてきた。CPUが複数の動作モードを持ち(やっと本格的なコンピューターになってきた)、メモリリソースの割り当てが柔軟に出来るようになっているため、無理にCで書くよりアセンブラーで書いたほうが手順がわかりやすいということも何となくわかる。

 ただ、完全にわかったわけではないから、現在のソースやスクリプトをどう変えて行けば、ターゲットマシンでうまく動くのかという具体的な手順はまだまだ見当がつかない。暫くは有りものを手探りで使っていくしかない。

 8ビットマシンのAVRから、いきなり32ビットのARMに移行しようというのだから少し無理があることは確かだ。本来の次のステップは16ビットマシンのH8なのだろうが、H8では設計が古すぎ、SPIが250khzどまりでは話にならない。H8/3069Fの900ページを超すデータシートも1/3まで印刷して勉強していたが、最終的なゴールを動画あたりまでとすると、どうも先行きがない。この際は、ちょっと無理をしてでも32ビットマシンにしておいた方が良いだろう。雑誌のオマケ基板でなBb_revb_top_numbered_2く、直接ARMを買うにしても今はそう高くない。

もう少しでBeagle BoardのRev Cを注文しそうになる(4/22/09)
 以前の記事(2/26)にも書いたハイエンドのCPUボードの新版がもう市場に出ていることを知った。ARMの情報収集をしていて迷い込んだ2ちゃんねるのサイトに出ていた。結構アンテナを立てていたのだが、なかなか普通のサイトでは出てこない。時々はこのサイトもチェックしておく必要があるようだ。

 この新版のRev Cは、基板に場所があるだけのUSBのホストインターフェース(写真の8)や、その他の不具合がほぼ解消されており、RAMが倍増して256MBになっているが値段は149ドルBb_revc_top_numberedと前のま まだ。日本円では¥17000ばかりで手に入る。日本ではDigiKeyのサイトから買え、すでに買った人のレポートまである。

 このボード何しろLinuxが軽々動きXwindowまで動くグラフィック機能を内蔵している。一時期Linuxにはまっていた がた老AVR研究所としては、今のことを放り出しても手に入れたい強烈な物欲にかられる。しかし、今はARMのJTAGインターフェースまで買って2つのARM基板を動かそうとしているところだ。それどころではない。

 それでもいつのまにか気がついてみるとPCの画面は、物欲の悪魔に誘われてDigiKeyのサイトになっている。「Linuxが動くからUSB経由で、インターネットもHDD接続も自由自在。お家サーバーとしては省電力で実用性は抜群」と悪魔がささやく。DigiKeyの発注画面を前にしてもう少しで注文のクリックを押すところまで行ったが、やっとのことで思いとどまった。

STM32基板でもJTAGコマンドが動いた(4/24/09)
 LPC2388基板がzusさんのサイトの助けを借りてEclipse上でロード/デバッグができるようになった。しかし、去年のARMの付録基板Cortex-M3(STM32F103)は取り残されたままである。同サイトにはこのSTM32基板の方の開発環境の設定ガイドもあるが、殆ど同じ手順を繰り返すことになっており経験値の向上には余り役に立たない感じがした。

 そこで、別の手順でオープンソースの開発を勉強することにする。雑誌のSTM32基板にはUSBからファームが書き込めるライター(Dfu)があらかじめROMに焼かれており、これを残した形で開発環境を作って行きたい。STM32用のサンプルプログラムは沢山あるが、殆どがこのライターを消してしまう。JTAGインターフェースを買ったのであまりこだわることはないのだが、書き込みの手段は複数残しておきたいからだ。

 調べるうち、このあいだのDWM誌2008年6月号4章のGNUの記事のサンプルプログラムがDfuを残して動くようになっていることがわかった。UARTもついていてちょうど良い。これを手始めにSTM32のGNU開発を進めることにする。

 Eclipse上ではなく、DOS画面からgnuツールのコマンドを入れていく。サンプルプログラムはWINARMのgnuツールでビルドしているが、こちらはCodeSourceryである。記事のコードを雑誌社のウェブから落とし、その改修のためMakefileを改めて詳細に見る。おや、このMakefileは相当コンパクトに出来ているのでわかりやすい。

 Makefileは、昔Linuxにはまって、カーネルビルドを繰り返した頃に少し勉強したが、このすさまじい変数置換と、恐ろしいまでのネスト構造に圧倒されて完全に理解するところまでは行けなかった。AVRでは、AVRstudioに任せてMakefileをさぼっていた。そんなに沢山のモジュールで構成するわけでもない組み込みコンピューターでMakefileを使うのは大げさすぎると思ったからである。

 改めて、基本から勉強し直す。先生はウェブにころがっているMakefileの入門記事である。その結果、沢山の派生機能はあるが、基本はそう複雑ではないことがわかった。暗黙的なルールというのがあるということ(単純なコンパイルではオブジェクトファイルだけの記述で良い)を、遅まきながら始めて知った。これが今までリストを見て良く理解できなかったところだった。

 今度のMakefileは簡単なものだったので変更するところはすぐわかった。要するに$CCとしているコンパイラーのパスを、/usr/local/arm-tools/bin/arm-elf-gccなどから、今度のgnuツールの置いてある\gcc\arm-none-eabi-gcc.exeなどに替えるだけで良さそうである。Makefileが入っているディレクトリ内のファイルはすべてあまさずコピーして持ってくることが肝腎なようだ。ひとつのMakefileはカレントディレクトリの中で完結しているからである。St32

 DOS画面上でmake allする。エラーもなく素直にビルドできた。JTAGはまだ動いていないので、例のDfuでUSBから基板に書き込む。うむ、うまく書き込めたようだ。これでジャンパーをオープンしてリセット(USBコードぬきさし)するとUART端末に数字がでるはずだ。PCのTera Termを立ち上げたが、つながっているはずのUSBの仮想端末が見えない。当然何も動かない。何か大きな勘違いがあるようだ。

St32jtag 記事を読み返す。ありゃりゃあ、プログラムのUART1というのはUSB経由の仮想UARTじゃない。別のピンに出ている普通のUARTのことだ。お馬鹿な勘違いである。基板はまだ何も実装していないので、ICピンコードでブレッドボード上のUSBシリアル変換基板と空中接続し、2本のUSBケーブルを基板とシリアル変換基板につなぐ。よーし、TeraTerm画面に何か出た。ボーレートを合わせると、動いた。動いた。LEDのON/OFFもキーボードから出来た。うむ、これで一歩また先に進んだ。

Ocd Eclipseへの持込みも、一旦新規プロジェクトを起こしてから、ファイル一式をフォルダーに放り込み、「refresh」すると、プロジェクトにすんなり入ることもわかった。快調、快調である。調子に乗って、STM32基板のマザーボードを作り、JTAGの20ピンソケットも実装する。今度はzusさんのサイトのSTM32開発環境の記事を参考に、JTAGまわりのソフトを整える。OCDを動かしてみた。問題なく動いた。少し勉強が進んだので、TelnetでOCDに入り、色々なコマンドを試す。視界をさえぎっていた霧が晴れて、段々周りが明るくなってきた感じである。

| | コメント (0) | トラックバック (1)

2009年4月21日 (火)

ARM基板にJTAGからのファーム書き込み成功

まっさらな付録基板にはJTAGから書き込めない(4/18/09)
 LPC2388付録基板にUSBソケット、JTAGソケット、ジャンパーピンをとりあえずハンダ付けして、いよいよ実験を開始した。OlimexのTINY-USB-JTAGケーブルのOpenOCDでの認識はDOS画面で認識を確認した。Eclipseに持ち込む。このデバッグコマンドのスクリプト入力が結構大変である。殆ど意味を理解しないまま、フラッシュ書き込みと、デバッグ開始のスクリプトを言われるままウェブ画面からコピーしたりして入力する。A4201806

 zusさんの解説サイトの指定どおり、OpenOCDをEclipseの中で立ち上げる。うむ、ちゃんと正しいメッセージが出ているようだ。次はフラッシュの書き込みである。ここで迷ったのが、CPUモードをISPモードにするジャンパーピン(JP2)の設定である。ファームをJTAGインターフェースからフラッシュに書くのだからISPモードではないと思うが、サイトには何の説明もない。リセットをいつするのかの指定もない。

 わからないときは何も考えずにやることだ。JP2をオープン(通常状態)にし、JP1(リセット)を押した後、フラッシュ書き込みをEclpseから指定した。しかし出てきたメッセージはどうも、ウェブに出ている正常終了のメッセージではない。フラッシュを書き込んだというメッセージが出ない。

出てきたメッセージを訳がわからないまま、一応追っていく。どうも以下のところからおかしい。

cpsr: 0xa00000f3 pc: 0x7fffe152
timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: 0
Runtime error, file "target/lpc2388.cfg", line 52:
in procedure 'mt_internal_rc' called at file "command.c", line 456

load main.elf
Error erasing flash with vFlashErase packet

メッセージ通り解釈すると、mt_internal_rcというプロセスでRuntime errorが起き、
main.elfというターゲットのバイナリをロードできないと言っている。vFlashErase packetというのがわからないが恐らく消去コマンドの名前だろう。このあと連続するエラーメッセージは、プログラムが書けていないためによるものと思われる。不思議なことにJP2をショート(ISPモード)させてリセットしたあとのISPモードでも同じ結果がでる。

 こうなるとこの先どうしたら良いのかもうわからない。いきなり大量の情報を放り込まれて頭の中は完全に飽和状態である。他のサイトもあたってみるが、思わしい手がかりはない。解説サイトのインストールの手順をその通りやったか詳細に確かめてみるが、どこも間違っていない。完全に暗礁に乗り上げてしまった。

 やれやれ、こうなったら一つ一つ要素を確認していくしかない。まずJTAGインターフェースがOCDのもとで動いていることは別の環境(DOS)で確かめられている。基板はどうだ。仮想シリアルのUSBが動いていることは、PCがCOMポートを認識しているので間違いない。本体のCPUはどうか。そうだ。雑誌の記事には別のライターでプログラムを書き込む手順が出ている。これでCPU周りを確認してみよう。

 早速、FlashMagicという書き込みプログラムをサイトからダウンロードし、雑誌のサイトからテストプログラムのバイナリーを落としてシリアルで書き込むことにした。順調にファームウエアが書き込まれた。リセットしてみる。おお、LEDが点滅を始めた。CPU周りもOKなようだ。 A4201812

 ここで何となく予感がひらめいた。このままもう一度Eclpseを立ち上げてJTAGを動かせばうまく行くのではないかという予感である。何の根拠もないが、昔こんなことがあったような記憶がある。 やるだけやってみよう。 JTAGケーブルをつなぐのももどかしく、Eclipseからフラッシュ書き込みを指示する。おや、出てくるメッセージが違うぞ。うまくいったかどうかはわからないが前とは別のメッセージだ。これは期待が持てる。

 出てきたメッセージを見直す。沢山の経過と警告のメッセージのあと、
wrote 1232 byte from file main.elf in ...... というファームが書き込まれたことを示す行を発見した。やった。やった。うまく書けたようだ。リセットしてみる。見事、LEDが点滅し始めた。思わずガッツポーズが出る。

 勘があたった。最初のシリアルライターのファーム書き込みで何かCPUの状態が変わったのだ。理由はまだ良く分からないが、AVRのフューズビットのようなものがARMにもあってCPUの環境が変わり、書き込みがOKになったような感じだ。Jtagload

 ここ一週間かかりきりになっていたARMの開発環境がやっと所定どおり動き始めたようだ。念のために、こちらのソースに少し手を入れてLEDの点滅間隔を短くし、ビルドし直して書き込む。よーし、JTAGで書き込んだ後は点滅が早くなった。間違いない。新しくファームがJTAGを通して書き込まれている。

 Eclipseのデバッグモードに入る。これも問題ない。ちゃんと指定のところで止まる。レジュームボタンを押すと点滅を再開する。いやあ嬉しい。まだ分からないことだらけだがとにかくARMでの新しい第一歩である。

やっぱりchaNさんのソースを使うのか(4/20/09)
 ARMの勉強を始めて、やっとプログラムの開発が出来る環境が揃った。LEDの点滅はもう良いだろう。次のステップに進もうと、参考になるプログラムソースを求めてウェブをさまよった。 

 このARMはどうもC言語のソースだけでは動かなく、必ずアセンブラーのスタートアップルーチンが必要なようだ。32ビットマシンなので最初の設定が沢山あり大変だ。これはお手本がないと、とてもまともに動かすことは出来ない。クロックすら所定のスピードにするために何段階かの手順を踏む必要がある。

 これからの腹案としては、AVRの時と同じように、UARTを入れてプロセッサーとお話をし、そのあとIICを入れてRTCを動かしたり、LCDをつけたり、最終的には、SDカードアクセスまで進むつもりをしていた。しかしなかなか手頃なソースが見つからない。

 ところが、このあいだダウンロードさせて貰ったchaNさんのLPC2000試食プログラムのソースを少し調べてみて驚いた。これは私が今からやろうとしているアプリケーションをすべて実現した完全なソースリストだ。

 さらによく見てみたら、スタートアップルーチンだと思っていたアセンブラープログラムは、割込みの制御と複数タスクをディスパッチする簡単なマルチタスクモニターであることがわかった。しかもSDカードの中身をダンプしたりするUARTのモニタープログラムまで入っている。うひゃあ、こりゃもうやることがない。

 折角、32ビットプロセッサーなのだからUARTから始めて少しづつ経験値を高めていこうと思ったのだが、ここにみんな解答が出てしまっている。恐れ入りました。WINARMの環境から、Codesourceryに移さなければいけないが、ここは素直にこのソースリストから必要なコードを少しづつ頂いてARMのお勉強をすることにしよう。

| | コメント (1) | トラックバック (0)

2009年4月18日 (土)

ARMの開発環境を作っている

オーバークロックの石は2.6Vでも動く(4/10/09)
 SDカードのLPCMプレーヤーのプロジェクトは一段落した。今は今後のために現用のリチウムバッテリーの長期テストをしている。満充電のあと、プレーヤーを動かした時間をこまめに記録し、そのときの電圧を測った。LEDをつけていない実装版は、消費する電流が音楽再生中で50mA程度である。バッテリーの容量は、830mAhとあるので16時間は持つ見込みである。ただこの公称の電池容量というのは連続放電であり、現在のテストのように通電と待機を30分くらいづつ繰り返すような使い方だともう少し伸びるかもしれない。Litiumbatt

 久しぶりに方眼紙を取り出し、小学生の実験よろしく電圧をプロットしていく。これはこれで結構はまる(やめられなくなる)。いつ過放電前の3.7V近辺の急峻なカーブがでてくるかわくわくしながら測っていくと時間がたつのを忘れる。 放電開始の4.1Vから電圧は少しづつ下がっていき、定格の3.7Vのあたりはむしろ電圧低下が少ない。あれ、測定間違いかといぶかっていると、突然、堰を切ったように電圧が下がり始める。3Vを下回ったあとは分単位で放電下限電圧の2.5Vに近づく。非常にドラマティックな放電カーブだ。

 結局、持続時間は少しづつ休んで動かしていたため、予想よりかなり長い間電池が持つことが分かった。想定では、17時間足らずの持続時間だったが、実際には19時間以上動いた。しかも20Mhzのオーバークロックの石は電源電圧が3Vでも正常に動く。ただ3Vを下回るとLCDは一気に薄くなり音が歪み始める。さすがに2.6V以下になるとMCUのクロックが動かなくなった。これなら過放電の心配はなさそうだ。とはいえ、音が出なくなることに気がつかなければ過放電させてしまう危険性はある。

お試し版の開発環境には乗らない(4/11/09)
 電池テストの傍ら、次のプロジェクトとして考えている雑誌付録で2つも揃ったARMプロセッサーの開発環境を整える情報収集をウェブでやっている。雑誌に必ずついているお試し版の商用のコンパイラーや開発環境は、もとから使う気はない。お試し版は無料だが、フラッシュサイズが限定されており、苦労してインストールしてもすぐに不満が出るのは見えている。A4181800

 これらの正規版が1万円内外なら、やっと慣れた環境を維持するため買ってしまいそうだが、幸か不幸か正規版は、安いものでも5万円以上、大抵の製品は十数万円のレベルだ。企業で使うならともかくとてもアマチュアが気楽に買えるレベルではない。雑誌の付録でプロセッサーを手に入れる対象は殆どがアマチュアか学生であろう。お試し版を無料で提供して正規版を買わせる魂胆なら、こんな料金体系は間違っている。余りうまい商法とは思えない。

 ソフトを有料にすれば、サポートに責任が生じる。まともなサポートをすれば、10万円でも下手をすれば元がとれないのは理解できる。割り切ってオープンソースのような無サポートの廉価版を出せば良いのだ。そうすればもっと製品は売れると思う。ウェブに情報が溢れている時代である。ましてやGNUという強敵と戦うには余りにも芸がなさ過ぎる。このままでは有料の開発環境の市場は狭まっていく一方だろう。

 こちらも当初から当然GNUプロジェクトのお世話になることにしていたが、基板を手に入れた頃は、オープンソースの開発環境はソースからビルドするような情報しかなく、少し手ごわいので様子を見ていた。

 ところが、PCMプレーヤーの開発が終わって改めてARM用のオープンソースの開発環境を調べてみて驚いた。いつの間にか沢山の環境の情報がウェブに溢れている。しかも、いわゆる人柱と呼ばれる先駆者がウェブ上でインストールの状況を報告してくれている。ありがたいことである。

 しかし、これが余りにも種類が多く目移りがしてなかなか決まらない。中身は皆同じgccらしいが、ちょうどLinuxが商用ベンダーによって多くのディストリビューションが生まれたように、数多くのプロダクトがでている。どれが良いのかはウェブで見る限りでは良くわからない。

 さらに、ファームを書き込むツールになるともっと種類がある。デバッガーにもなるJTAGインターフェースを使った本格的なものから、単純なパラレルやシリアルライターまでありこれも何を選んでよいのか迷ってしまう。FatFSでお世話になっているchaNさんも、最近、この雑誌の付録基板の応用を紹介されている。何と、自前のプログラマーとシリアルで書き込むライターの回路図まで用意してある。とても簡単そうだ。

 これに強く動かされたのだけれど、定番のJTAGインターフェースをマスターしてみたい気分がまさり、今度は市販の安いJTAGインターフェースを買ってみることに決めた。これも自作できそうだが、不確定要素を減らすためこの際は我慢して既製品を買うことにする。1万円以下というのが私の場合このあたりのトレードオフのようだ。

 それに、統合環境で名高いEclipseも使ってみたかった。で、ウェブの紹介記事の中でも、一番詳しいここの記事(http://homepage3.nifty.com/zus/index.html)を頼りにターゲットを定めて開発環境を作っていくことにした。このページは実に懇切丁寧でとても有難い。このまえのCortex-M3の開発環境まである。

Eclipseでのビルドまで成功(4/12/09)
 オンチップデバッガーのZylinプラグインのインストールにてこずったが(サイトのURLが変っていた上に、一時不安定で超低速のダウンロード)、何とか、Eclipseのコンパイル環境は出来上がった。おそるおそるサンプルのソースをプロジェクトにしビルドしてみる。おお、問題なく成功した。Elfファイルが出来る。ファーム書き込みは、このサイトでは、OlimexのTINY-USB-JTAGケーブルを使うことになっているので今は、これから先は進めない。

 そのかわり、前回のCortex-M3のとき雑誌についていたCD-ROMにある STマイクロのライブラリとデモプログラムをEclipse下でコンパイルしてみた。Makefileとリンカースクリプトは、デモサンプルのものを丸々流用する。しかし、これは通らなかった。

 何故か、関数未定義のエラーが出る。プロジェクト内にはその関数を定義するヘッダーファイルや、ソースファイルが入っているのに認識しない。Makefileは他からの借用で、恐らくライブラリのパスの問題だと思うが、Makefileはうろおぼえの知識しかないので手が出ない。EclipseにはMakefileを作ってくれるモードもあるらしいが、ここも手探りでなんとも先に進めない。まあ、こうやって模索しているうちに少しづつ分かってくるものだ。深追いをしないで、これ以上の追求は諦める。

OlimexのARM-USB-TINYケーブルを買ってきた(4/14/09)
 お世話になっている開発環境インストールのサイトが採用しているJTAGインターフェースを買ってきた。始め通販で注文しようと思ったら、行きつけの千石電商で販売していることを知り、仕事の帰り早速買ってきた。\6825。USBのJTAGインターフェースとしては安価だが、がた老AVR(ARM?)研究所の投資レベルとしては決して少なくない出費だ。

 このTINYの上位機種のARM-OCDと全く同じ仕様と思われるJTAGケーブルの自作記事が2008年6月のデザインウエーブ誌に出ているが、今回は安全策をとった。前にも書いたように自分は余りデバッガーを使わない。人の書いたソースならともかく、自分が書いたコードのデバッグにソースコードデバッガーを持ち出すのは抵抗があるからだ。しかし、今度は新しいチップだ。用心に越したことはない。それに、組み込みの定番のJTAGインターフェースに習熟しておきたいこともある。FPGAのJTAGパラレルインターフェースは自作してファームの書き込みに使ったけれど、それきりになっている。

 TINYという名前通り、DSUB25ピンコネクター程度の小ささで、ケーブル側がUSBソケットBタイプ、ソケット側が20ピンのJTAGインターフェースになっている。早速分解したいところだけれど、Olimexのシールが張ってあって保証が切れることになっている。分解は動いてからにしよう。Olimex

 ターゲットマシンの準備を全くしていないことに気がついた。とりあえずは直近の付録ARMのLPC2388基板を動かすことを考える。この基板、残念なのはせっかくRTC(リアルタイムクロック)用の石がつけられるのに電源が主電源と一緒に配線されてしまっていて、バッテリーバックアップができないことだ。時計はSDカードの書き込みなどファイルシステムには欠かせない情報なのだが惜しい。基板を確かめてみたが、バッテリーバックアップ電源ピンの配線はチップの下のパターンになっており改造は不可能。ピンを切って配線できなくもないが、ルーペを見ながらの半田付けは困難を極めそうだ。

| | コメント (0) | トラックバック (0)

その他のカテゴリー

ARM | AVR | EAGLE | Xbee | 電子工作