« 2012年1月 | トップページ | 2012年3月 »

2012年2月の2件の記事

2012年2月19日 (日)

STM32F107でTFT液晶基板が動くまで

 Aitendoの生STM32基板は、STM32F107VCT6を載せ、USBの仮想UARTモニターが動くところまで来た。このプロジェクトの最終目標は、この基板にTFT液晶をつけ、グラフィック気圧計を作ることだが、スランプから抜け出せていないので、どうも歩みがのろい。色んなところで道草を食いながらの電子工作である。

仮想UART端末のUSBストリームをロジアナでプローブする(2/7/2012)
  ダブルバッファーを採用してSTM32F107の仮想シリアル端末(VCOM)は、無事、大量のデータをPCに送ることに成功した。しかし実は気がかりなことが残っている。送信の最初に必ず1バイト無駄なデータを送ってしまっているのだ。

 一旦送信ストリームが始まれば送られないし、送っているデータは、0X00という無効(端末に表示されない)データなので表面上は見えない。シリアル端末で操作している限り問題は出てこないが、気分は良くない。1バイトだけとはいえ、ゴミはゴミである。成功したといえるレベルではない。

 何故、こうなったかというと、最初0バイトのデータを送ったところ、新しいUSBライブラリのエンドバッファー書き込み関数SIL_WRITE()が、割り込みルーチンの中では終了割り込みが入るのに、ユーザー側で0バイトを書くと終了割り込みが起きないのである。

 このままだと永遠に送信が開始されない。それで仕方なく、1バイトのNULLデータを送って割り込みを開始するようにした。何とか大量のデータ送出は問題なくなったが、前の記事をアップした後も、これが気になっていろいろと考えていた。

 しかし、ダミーデータを送らなくても送信を開始できるロジックは、考え出してみると、何故、これに気がつかなかったのかと思うくらい簡単なロジックになった。やりかたは簡単で、最初の送信要求1バイトは、バッファーに書かず、直接SIL_WRITE()でエンドバッファーに書き込み、この終了を待って、次の送信要求をバッファーに書いていく。

 こうすれば、最初の1バイトを送ったあとの割り込みが割り込みルーチンに入り、バッファーに入っていたデータが送られていく。最初から有効データなのでゴミは送られない。このあとの送出は、バッファーに書き込まれるだけなので、データの送り込みと、SIL_WRITE()の書き込みは分離される。よし、これで良い筈だ。機嫌よくテストに入る。と、これが反対に頻繁にデータの欠落が起きるようになってしまった。おかしい。正しくデータが入るはずなのに何故だ。

 実は、この仮想端末には極くまれにしか起きないが、まだ不具合が残っている。SIL_WRITE()が少量データを書いたときに限って(リターンキイのみなど)、前のデータを一部重複して出力することがある。USBのハード割り込みがデータ処理時に入ってしまうからかもしれない。

 今度の改良は、この不具合に巻き込まれたのだろうか。ちょうど良い機会なので、トラブルシューティングのために、ロジアナで、実際にUSBにデータを送り出しているところまで徹底的に詳しく調べることにした。 

S_p2094624 ストロベリーリナックスで大枚4万をはたいて買ったロジアナである。200Mhzの分解能を持っている。プロトコルアナライザーにもそこそこ使える。しかし、現在のUSBの主流2.0はサポートしていない(USB1.1はサポートしているが)。

 何故だろうと、ウェブを探して事情が良くわかった。2.0のUSBを見るには、本格的には50万円以上する測定器が必要なのだ。2.0には480Mbpsのハイスピードモードがある。4万足らずのロジアナで見られるわけがない。それでも、中には10万クラスのアナライザーもあるようだが、いずれにしても業務用でアマチュアの手の出せる世界ではない。

 でも今使っているフルスピードクラスは12Mbpsなので、どんな信号か調べるだけならこのクラスのロジアナでも十分把握可能だ。リチウム電池の充電用に作ったUSBのAプラグ、Bプラグ、5Vアダプターコンセントの基板に、ピンソケットを追加して、USBの信号線を途中で取り出せるようにした。

 よーし、USBのデータも見えるようになった。USBがアイドルのときのほうがホストとのやりとりが頻繁で、一旦データ送信モードになるとパケット通信的にデータをひとまとめにして送っているのが良くわかる。

Usb11 SIL_WRITE()が少量のデータ送出で極くまれにデータを被って送出する時があるのは、USB本体の割り込みと重なっているからと考えていたが、USBへの送出はかなり時間がたってからであり、それが原因ではなさそうだ。それにしてもおかしい。データが欠落するのは最初だけではない。

 ロジアナでは中身のデータまで調べ切れない。LEDのプローブをあちこちかけて調べる。散々調べて、原因はやっぱりこっちの基本的ミスとわかる。修正のときにバッファーの順番を間違えてしまっていた。ユーザーが書き込んでいる最中のバッファーをエンドポイントバッファーに書き込めば、おかしくなるのは当然である。

 順番を換えて(というより元に戻して)、無事、前のような正確な送出に戻った。ホッと一安心である。これでみなさんに自信を持ってソースコードを使ってもらえる。

 以下にEclipseのプロジェクトとして入ったソースコード一式をzipファイルの形で置きます。前記事同様、libフォルダーが削除されていますので注意してください。前回のコードは破棄してください。

「pub20712_STM32_VCOM3.zip」をダウンロード

秋月の¥1000のステッピングモーターを試す(2/8/2012)
 プロジェクトが進まない時は、気分転換が一番である。秋葉原にもご無沙汰だったので、仕事の帰りに久しぶりに秋月電子に寄った。最近売り出したステッピングモーターを買うためである。

 秋月には、このところマイクロマウスなどに使えそうな適当なステッピングモーターがなかったが、最近、手頃な大きさのものが売り出された。価格も¥1000と安く種類も多い。

 マイクロマウスは、中級者まではステッピングモーターが良く使われるようで(上級者は強力なDCモーター)、前から欲しかったのだが、ウェブに紹介される定番のモーターはどれもひとつ¥5000近くし、ちょっと手が出しにくかった。マウスにするなら少なくとも2台はいるので一回の投資額は1万を超える。どこまで本気でやるか決めかねているときに、この額は大きすぎる。

 一個¥1000なら気楽だ。5Vのユニポーラにする(前の回路がそのまま使える)[ST-42BYG0506H]。テストのためだけなので1台だけである。これまでのFETドライバーに、いそいそとつける。ありゃあ、全く動かない。シャフトをさわると電源を入れるたびにピクピク動いているので配線間違いの可能性が高い。

 接続ケーブルの撚り導線の色は前のステッピングモーターと全く同じ色の組み合わせである(赤、黒、白、青、緑、黄)。これって組み合わせは同じだけれど結線は統一されてないの? ああ、やっぱり。説明書を確かめると結線がこれまでのモーターとは全く違う。そうだよね。こんなものまで規格が統一されていると考える方が甘い。しかし、それなら色を合わせるなよと、かげで八つ当たりする。

S_p2124625 スペック通り、つなぎなおすと無事、勢い良く廻り始めた。逆転も停止も順調。42ミリ四方のステッピングモーターだ。一相あたり0.5Aだが、手で回転を止めようとすると220グラムのモーターが動くほど強力だ。回転は余り速くない。FETドライバーなので十分電圧は来ているはずだが。

 早くしようとタイミングを少なくしていくと、突然停止した。脱調ではない。うーむ、制御が難しそうだ。電源は2.3AのACアダプターで、動作時は、0.5Vほど下がった4.5Vになる。もっと強力な電源が必要なのだろうか。マイコンと電源を共有しているのがまずいのかもしれない。

 一時間以上、連続で回しても、モーターは、ほんのり暖かくなる程度で全く問題ない。FETの方は気がつかないくらいの温度上昇で、これも大丈夫。ACアダプターも熱は持たない。このトルクならギヤを使わず直結でマウスが動きそうだし、カーテンの開け閉めくらいなら楽勝だ。色々なところで使えそうである。

AitendoのTFT液晶を動かすことに取り組む(2/11/2012)
 やっと、TFT液晶を作りこむ意欲が戻ってきた。STM32基板と、TFT液晶モジュール基板を前に、あれこれレイアウトを検討する。ソースコードは、ねむいさんのコードを有難く頂戴してある。

 STM32などの32ビットプロセッサーに小さなTFT液晶をつけ、画像表示やファイラー(SDカードのファイル操作)にする工作は、このあたりのクラスの電子工作では定番で、ねむいさんを始め多くの先人が、既に成果をたくさんウェブ等で発表されている。

 こちらの工作のグラフィックの目的は、気圧の折れ線グラフを描くだけだが、今後(気圧計以外にも使うこと)を考慮して、TFT液晶とCPUの間は、16ビットインターフェースを選ぶ。AVRと違ってピンが多いので問題ない。これなら動画まで余裕のはずだ。記録装置は、気圧計ならSDカードまでは不要で、フラッシュROMくらいで十分だ。

 しかし、ねむいさんのソースは、SDカードのファイルシステムから、RTC(リアルタイマークロック)、タッチパネルセンサー、JPEG画像送出まで盛りだくさんの機能がついたソースである。英数字や漢字が画面上に出るのは嬉しいが、このソフトをいじらずに動かすためには、SDカードスロットや、RTC、タッチパネルなど沢山のハードを盛り込まねばならない。

S_p2124640 動いているソースコードから機能を外していくことは結構難しい。下手にソースをいじって動かないと頭を抱えるより、ソースをなるべくそのままにして、とりあえず動くことを狙う。カストマイズしていくのは動いた後やる方が、安心して改造できる。

 幸い、RTCはつけてあったので、SDカードをつけるだけで実現できそうだ。タッチパネルインターフェースはMakefileで分離できるようになっていたので未実装にした。フラッシュも200KBを越える。

 TFT液晶モジュールをどう実装するかは頭の痛い問題だった。考えた末、結局、みんながやるようなスタック構造にすることにした。意外とこれが最近の流行だったりする(例の雑誌付録のMARY基板あたりからか)。できあがった形は、LANインターフェースをつけないのにマザー基板(CPU),SDカード基板、TFTモジュールの3段スタックになってしまった。

S_p2124633 はじめにTFTのバックライト部分だけを配線。これは簡単に点灯した。おやあ、画面の右側に傷がついている。うーむ、安いだけのことはある。まあ、致命的な傷ではないので目をつぶろう。

TFT液晶が表示されない(2/15/2012)
 実装を続ける。高速をねらって16ビットバスにしたので配線量が多い。しかもピンヘッダー2つの間を表裏に配線するのは、とても間違いやすい。SDカード部、データバス上部8ビット、下部8ビット、TFT制御ライン、通算4日かかって全部の配線をやりおえた。最近は根が続かない。

 ファームは大分前にNO ERRORになっている。フラッシュは、最初ビルドした時は、240KB以上あって、107でも入るか冷や冷やしたのだが、タッチパネルの部分を外し、ねむいさんの助言に従ってTFTドライバーの初期化コードをILI9325だけに絞ったので、200KB近辺に納まった。

 中華シリアルローダーは快調に200KBを書き込んだ。こいつ時々こける(書き込めないと怒る時がある)が、リトライすると大抵、素直に正常終了する(本当に書いているか時々心配になるが)。

 いよいよ通電である。緊張の一瞬。祈る気持ちでUSBプラグを差す。TFTの画面が白くなる。パイロットのLEDが点灯。しかし、モニター端末からは何の反応もない。画面も白いままである。まあ、初めから動くとは考えていない。とりあえず電源を切って、あちこち触り、どこも熱を持っていないことを確かめる。

 モニター端末が動かないのは、見当がついている。AitendoのSTM32基板は、RS232Cインターフェースを持っており、標準のUART1とUART2を選べるようになっているが、オリジナルのねむいさんのソースは、UART2がリマップされているので、これが使えない。リマップした理由は、SDカードのSPIのSSピンと被るかららしいが、SSピンはSDカードのインターフェースでは使っていないので大丈夫だと判断し、リマップを止めて正規のUART2に戻してある。

 それが良くないようだ。リマップするからには何か理由があるはずだ。ここはやっぱりリマップされたPD5とPD6をUARTに出した方が良い。ピンヘッダーを出してPD5、6を取り出す。コンパイルし直して、ピンにUART線をつなぎ再度テスト。よーし良いぞ、端末に文字が出た。しかし、化け化けの文字だ。

 おう、TFTの画面にも何か出ている。中央部だけだが、これも完全に字が乱れている。ふーむ、何かクロックが違うような症状だ。クリスタルは指定どおり25Mhzになっているが、それがおかしいのだろうか。このあたりは8ビットプロセッサーと違って、非常に複雑なところでとてもソースを追いきれない。

 仕方がないので、ロジアナを持ち出して、シリアルのパルス幅を計測することにした。ソースの指定は230kbpsになっている。出てきたパルスの時間間隔を測る。8ビットが34.705μs。230kbpsは、正確には230400bpsで、この8ビットは34.722μs。ふーむ、0.1%以下の誤差だ。殆ど正しい。クロックは問題ないようだが、それでも字が化ける。おかしい。

 バイナリー端末のAcknowrichを動かしてみた。何い、こいつは230kbpsはサポートしていない。うーむ、そうか、PCにも厳しい速度のようだ。こんなに早くなくても良い筈だ。少しビットレートを落としてみよう。当研究所のシリアルの定番の早さ38400bpsにして再ビルドする。

遂にTFT液晶(YHY024006A)が正常に表示された(2/17/2012)

 良いぞ。端末にソースコード通りのメッセージが戻ってきた。入力も受け付ける。RTCも動いているようだ。ソースコードはなるべくいじらないようにした効果が出たようだ。SDカードからデータを読んでとりあえずはファイラーまでは動いた。

Tft しかし、TFT画面は中央部に乱れた文字らしいものが出るだけだ。これもクロック関係の不具合に見えるが、ソースがこれだけ動いているのだから、やはり配線間違いが一番疑われる。

 夕食後、気を落ち着けて、TFT基板とマザー基板の間の結線をひとつひとつ確認していく。一番有力な疑いは、16ビットモードでなく、8ビットモードでTFTが動いている疑いである。このTFTは情報によればデフォルトでは16ビットモードとあるが、本当にそうなのか確認する術がない。

 もういちど雑誌記事(トラ技2011年2月号)や、著者のサイトを見ているうち気になるところが見つかった。IM0というピンは雑誌では結線されていないが、データシートを見ると16ビットモードではグランドに落とすことになっている。

 モジュール基板では、既にグランドに落とされているので雑誌のように未結線で良いと解釈していたが、本当にグランドに落ちているのか調べてみることにした。やった。これだ。手元の基板のピンIM0はどこにもつながっていなかった。これに違いない。8ビットモードになってしまっている。これが画面が乱れる理由だ。

S_p2184650 いそいそと、ハンダごてに電気を入れ、IM0とグランドをつなぐ。さあ、どうだ。おーし、画面が出た。ひやあ、小さいけれどファイルリストが出た!これは小さい。端末のキーを押すと、画面が消えてシリアル端末の動作だけになってしまうが、間違いなく日本語のファイル名も見える。

 タッチセンサーを動かさないとTFTのファイラーは動かないと思っていたが、ソースコードを見て、コントロール+キー(いわゆるCTR+char)でファイラーが操作できることがわかった。うわあ、BMPだけでなく、JPEGの画像までが表示される。すごい。

 テキストファイルは? これは残念ながら表示されなかった。ソースコードを見て、つい実装したくなるが我慢する。目的は、グラフの描画である。

S_p2184658

 とにかく、今まで作りこんできたSTM32基板に2.4インチTFT液晶モジュール(YHY024006A)をつけたグラフィック気圧計の母艦部分がやっとのことで動いた。これから、任意の図形を画面に描くのは、また、ひと苦労だろうけれど、何とか一段クリアした。このあたりでブログに報告しておこう。

 今回の経験で人さまのソースコードを貰って動かすためのノウハウが多く学べた。自分のためにも、同じようなことをやる他の方の参考にもなると思い以下にまとめてみた。

人のソースを動かすときの教訓:

  • ソースコードはなるべく触らない
    (UART2を下手にいじって苦労したことを忘れるな)
  • 出来るだけ同じ環境に揃える
    (原典と違うところを徹底的に洗う努力があれば解決は早かったはず)
  • 悪いのは全部自分。ソースは間違っていない
    (何しろ動いていたのだから。動かないのはみんなあなたのせいである)

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

2012年2月 4日 (土)

STM32F107でやっとUSB仮想端末が動いた

 前回の記事以来、もう20日近くが経ってしまった。何故か2012年の電子工作は遅々として進まない。特に他の事で忙しいというわけでもない。ただ、どういうわけか意欲が湧いてこないのだ。とりとめもないことばかりに時間が過ぎて気分が乗らない。いわゆるスランプというやつだ。

 まあ、こういうときもある。人生にはまだまだ時間がある(そうゆっくりもしていられないが)、たいした成果も上がっていないけれど備忘録を兼ねてこの間の経過報告をしておくことにする。

S_p1314614

やっとDFUが動いてプログラムが書けた(1/16/2012)
 生基板からのSTM32プロセッサー基板がやっとのことで動いて、プロジェクトは次のステップ、ファームの開発に移った。統合環境Eclipseを立ち上げる。EclipseでのSTM32のソフト開発は、フォトフレーム以来ほぼ1年ぶりだ。

 半年前にはFreeRTOSをやっていたが、同じARMでも石はNXPのLPC2388で微妙に環境が違う。情けないことにEclipseはともかく、STM32のプログラミング環境などは見事にみーんな忘れていた。

 リハビリのつもりで、少しづつ以前のプロジェクトのソースコードを見ながら、ブートローダーから先の手順をゆるゆると進める。CPUは、前の騒ぎでSTM32F103に戻ってしまっている。103と107はピンコンパチで、こんどのグラフィック気圧計は、特に107でなくてもかまわない。何しろ100ピンのCPUの換装はおおごとだ。とりあえずは103のままプロジェクトを進めることにする。

 まずはCQ-STARM基板の状態にもどそうと、ブートローダーからDFUを焼くことにする。ファーム書き込みの手段は増やしておきたい。中華シリアルプログラマー、MCUISPは好調だが、いつ何時動かなくなるかわからない。STマイクロ純正のライターFlushLoaderは、103に戻したら動かなくなっている。用心に越したことはない。

Ws000000

 もう4年も前になる付録の雑誌号を引っ張り出して全体を復習する。DFUそのものは、以前ねむいさんのところから頂いたソースを使う。MCUISPは快調にプログラムを書き込んでくれるが、一向にUSBが動かない。PC側のプログラマーDFUseが基板を認めない。

 そのうち、DFUモードというのがあって、I/Oピンのひとつをグランドに落とさなければDFUにならないことに気づいた。基本的なところをすっかり忘れている。お馬鹿な話である。早速、PB9を1kΩでプルダウンする。ただ、このソースがこのピンで良いのか確認するのにえらい時間がかかった。考えてみれば、このDFUはCQ-STARM基板用なので確認する必要もなかったのだが、何しろ昔のことで周りがすっかり見えなくなっている。

 最初、動かなかったが、何度かUSBを抜き差ししたり、リセットを押しているうちに、PCのディバイスマネージャーのところにDFUのアイコンが出た。 コネクターに抵抗を差し込んでいたのが接触不良だったらしい。DFUseを立ち上げると、ちゃんとボードを認識した。

 しかし、このあとも難儀が続いた。DFUで適当なプログラム(仮想UARTモニター)をファームに書き込んだのは良いのだが、このプログラムが動かない。さっきのピンをはずしてもプログラムモードに行かないのである。

 これも、このピンをプルアップしなければならないことを忘れていた。Vccから1kΩをつないで無事、USBを通した仮想UARTモニターが動いた。やれやれ、これで一段落である。¥450のCPUボードがやっと日の目を見た。

103から107へまた換装しなければならない(1/19/2012)
 勢い込んで、ねむいさんが最近、集大成してくれた、STM32ファミリーでこのTFT液晶が動くソースコード一式をネットからダウンロードした。当初はスクラッチからTFT液晶のコマンドレベルのドライバーを書こうと意気込んでいたのだが、ウェブで上記のソースを見つけた途端、意欲が一気に失せた。

 へそ曲がりではあるが、意気地のないへたれである。折角、先人が苦労して作ったものを使わない手はない。何も無理をすることはないと勝手な理屈をつけて、ありがたくソースを頂戴する。このソースは、ChaNさんのFatFSが入っており、ファイラーにもなる。

 ハードはまだ未配線だがビルドだけでも通してみようとEclipseにソースチェーンを展開して、コンパイルの準備をする。このソースは、107用のソースなので103向けに換えてやらなければならない。MakeFileで103の環境変数を設定する。しかしmakeは何故か最初のところで門前払いである。

 ファイルではなくコマンドがないと怒っている。暫く悩んでいたが、MakeFileに新しく追加されていたシェルの置換ステートメントを訳わからずにコメントアウトしていたことがわかり、これをはずしてやっとコンパイルが進み始めた。

 いくつかのライブラリ定義漏れを修正して、これは通りそうだと思っていたら、見かけないエラーでビルドが止まった。エラーメッセージを読む。あっちゃー、フラッシュサイズオーバーだ。このTFT液晶+FatFSモデルは、要求メモリとSRAMが大きく、フラッシュ128KB、SRAMが20KBのSTM32F103VBT6では動かないことがわかった。「振り出しに戻る」というやつである。

 仕方がない。折角つけて正常に動いていた103をはずすしかない。107に移し変えなければ先に進めない。3回目のLQFPのハンダ付けはさすがにきつい。一度外した面実装のICチップは、ピンをいくら目視で揃えても、あちこちが微妙に歪んでいるので、ハンダ付けをルーペで見直すと、冷や冷やするところが続出している。

 下手にやり直すのは危険だ。前やったようにパターンごとはずす恐れがある。この基板は安いだけあって、パターンが弱い。気楽にはいじれない。それでも、どうしようか迷うところが数箇所ある。ハンダ付けは問題ないようだが、ピンと隣のパッドが近接して危ない。

 何度もルーペを換えてチェックしたが、結局そのままにすることにした。テスターでショートだけはしていないことを確認する。思い切って通電する。よーし、ブートローダーまでは通った。各ピンが本当につながっているかどうかの確認は実際にそのピンを使ってみないとわからない。とりあえずは、これで行こう。

STマイクロのUSBライブラリが大きく変わってしまった。(1/20/2012)

 103のときと同じ手順で先に進む。まずDFUのソースをSTM32F107で動くようにMakeFileを調整する。何とかビルドが通った。テストする。順調にMCUISPと、フラッシュローダーが107を認め、DFUの書き込みに成功した。DFUSeが107で動いた。ねむいさんが以前ブログで指摘していた107のブートローダーのERRATAは幸い発生しなかった。まあ、まだ何もペリフェラルをつないでいないからだろう。

 次はDFUそのものの動作確認である。103で動いたUSB仮想端末モニターのファームをロードしてみた。何の問題もなく書けた。しかし、モニターは動かない。PCでは不明なディバイスと表示されるところまで動くが、仮想UART端末としては認めないのである。

 動かない理由はすぐわかった。USBライブラリが古すぎて107では動かないのだ。2年前に開発したUSB仮想UARTモニターは、雑誌についていたSTマイクロのUSBライブラリV1を使っている。107はV1では動かない。

 それなら仮想UARTモニターのUSBライブラリを107が動くV3に換えれば良さそうなのものだが、これが難しい。STマイクロのUSBライブラリーはV1からV3で、大きく変わっている。というより、103と107では、USBそのもののハードが変わっていて(107はUSBのOTG機能が追加されている)、ユーザープログラムで使っていた関数や変数が殆ど変更されている。ライブラリを単にV3にしただけでは、次から次に未定義エラーが出る。

 こうなると意地になるのがいつもの癖である。冷静に考えれば、元々は気圧計のためにSTM32F107を動かそうとしている。そこでUSBが動こうが、動くまいが本筋とは関係ない。さっさとやめて本来の開発に戻れば良さそうなものだが、これが出来ない。

 103で快調に動いていたダブルバッファーを使った仮想UART端末が新しいチップで動かない(動かせない)というのが、しゃくなのである。変なこだわりがある。このまま放置して先に進めないのだ。まあ、このへんがアマチュアの特権である。やりたいようにやる幸せ(?)をかみしめて、こだわることにする。

 暫くEclipse上で苦闘する。未定義変数を検索して必要なドライバーを探す。Eclipseのサーチ機能は強力なので、どこで定義しているかはすぐわかる。あれえ、ちゃんと定義されているのにエラーになる。おかしいな。そのうち気がついた。ソースコードにあっても、107を選んだ時に#ifdefなどのプリプロセッサーでなくなってしまう。ひとつひとつのソースレベルまで見ないとわからない。

 半日近く、ソースをいじりまわして納得した。これはやっぱりあきらめるしかない。107には、103と違うハード(USBのOTGなど)がついているので、ライブラリの構造が大きく変わっている。今までのやり方の手直しぐらいでは動きそうもない。USB仮想UARTは道半ばだが、諦めることにする。ロードが大きすぎる。それにこれが目的ではない。

 ようやく、あきらめた頃である。何とウェブでまたも、ねむいさんの記事がヒットした。STM32F107でVCOM(USB仮想UART端末)を動かしたデモプロジェクトである。なんだ、なんだ、ちゃんと動いているソースがあるじゃないか。またまたねむいさんである。ありがたくソースをいただいた。

STM32F107の仮想UARTのソースでも泥沼(1/23/2012)

 ねむいさんのソースは、STマイクロのV3ライブラリのVCOMのデモがベースになっているようである。実はこれを探していたのだが、自分では見つけられなかった。みんなが言っているようにSTマイクロのサイトは欲しい情報が実に探しにくい構造になっている。誰のためのサイトなのだろう。

 ビルドそのものは、前に一回通しているので、Makefileの修正は楽で、順調にビルドは進んだ。MCUISPでファームを焼く。このSTマイクロのVCOMデモソースは、標準のUART1とUSB仮想UARTをつなぐブリッジ機能のデモである。USBケーブルを差し込んで電源を入れる。良いぞ、PCが107のUSB仮想UARTを認めた。これで一歩前進だ。

 次に、PCのシリアル端末ソフト(Teraterm)で、通常のCOM1のシリアルコンソールも立ち上げる。2枚のシリアル端末を前にしてキーボードを叩く。しかし、どちらから打ってもデータは行き来しない。

 うーむ、ビットレートが合っていないのか。ソースコードの通りUSB-UARTを11520bpsパリティ無し、ストップビット1、COM1を9600bps、奇数パリティ、などとするが、うんともすんとも言わない。

 こちらの目的はCOM1とつなぐためではなく、前やったように単にUSBの仮想UARTを動かしたいだけである。不確定要素のあるハードのCOM1のUARTの方は余計だ。コードを削って、前にやったような仮想UARTモニターにしようとソースをいじり始めた。

 しかし、このVCOMのソースコードは何かおかしい。特に、USBのエンドポイント周りのコーディングは、同じような処理が複数あって混乱する。新しく加わった新機種(STM32F107クラス)のために#ifのプリプロセッサーで分けて機種ごとにコードを追加しているので余計読みにくい。ソースコードが年を経て劣化するというやつである。安易な#ifの使用は、あとが大変で、こんなコードを書いていると、書いた本人でもこの先メンテナンス不能になるのではないかと心配になる。

 それにしても、UARTとUSBのバッファーの間のデータ移動ロジックは稚拙としか言いようがない。受信したUARTデータのサイズとUSBのパケットサイズを比較しながら無理やりデータを移している。まるで素人が書いたようなプログラムである。

 要するに目の前のデータの形に気を取られて、本質がわかっていない。こういうときは、ストリームの概念を持てばプログラムは非常に簡単になるはずで、少し大きめのリングバッファーかFIFOに一旦データを移して、そこからUSBのエンドポイントのパケットサイズ分を採っていけば良い。

 それにしても、ひどいコーディングだなあと思っていたら、違う視点でこのコードの不安について書いているサイトを見つけた。

全く同感である。USBの割り込みが2箇所あって、排他処理しているのは良いが、全く同じような処理が重複している。バッファーの終端処理が考えられていない。このページの通り、バッファーを使っているのに、リングバッファーとして使わず、2048バイトという大量の容量にして、その管理をサボっている。

 そもそも、オリジナルのソースでは、UARTの速度が9600bps、USBが115200bpsなのに、USBからのデータは受け取るばかりで、ソースには何らかのフロー制御をしている形跡がない。フロー制御をしなければバッファーをどんなに大きく(2KB以上)とっていても、持続して送受信を続けることは出来ない。

 こんなソースを書いてはいけないという見本のようなものだが、悪態をついたところで正しい修正が行えるわけではない。黙々と、少しづつ直していくしかない。しかし、スランプなので、集中してデバッグする気力がなかなか生まれない。

やっとのことでVCOMが動いた。しかし不安定(1/28/2011)
 やれやれ、やっとSTM32F107の仮想UARTが動いた。しっかし、えらい時間がかかった。やっぱり、ヤキが廻ったとしか言いようがない。モチベーションが低い時に作業を無理に進めると、こういうものである。

 USB仮想端末は、実行のたびにUSBケーブルを抜き差ししないと動かないことを思い出し、動き始めた(最初から動いていた)のは良いが、どうしても文字化けが解決しない。1文字のエコーバック程度なら問題ないが、複数データの送信では正しく送られない。

 ねむいさんのブログにも、このソースについての不安が同じように出ていたが、わかってしまえば、いつものように自分のお馬鹿な基本的ミスで、とりあえず問題は解決した。USBのエンドポイントバッファーに書き込む配列の番号がオリジナルのままになっていた。これでは、常にデータを送り終わったところが始点で、いつもゴミを送ることになる。字化けするはずだ。

 これをバッファーの最初、&EP_Buffer[0]にすることで字化けしていた複数データは一応正常に表示された。やれやれ。しかし謎が残る。何故1文字の時、正しく出たのだろう。1文字のときでも化けるはずなのだが、1文字の時は正常に送出される。謎である。

 とにかく、前のV1のライブラリを使った103の仮想UARTと同じような動きはするようになった。ただ、まだsystickを使ったタイマーは動かないし、ちょっと多量に送ると半分以上欠落するし、頻繁にハングする。まだボロボロでとても完成と言える状態ではない。

V3から導入されたハードのエンドポイントバッファーに書き込む関数SIL_WRITE()が不調である。パケットサイズ一杯に送ると、データを半分以上落としてしまう。パケットサイズの半分にすると、大体動くが、それでも4 KB以上を一気に送ると、ハングしたり、データの欠落があり安定しない。それにしても、このVCOMのコードはV3になっても色々なところでたたかれているようだ。

 でも、まあ、とにかく、USB仮想UARTは動いた。これでやっと、VCOMの縛りから逃れられた。そろそろ本筋のTFT液晶の工作に移らなければいけない。

脱線ついでにSTM32でタイマーを実装(1/31/2012)
 と、意気込んでは見たものの、一向に工作の意欲が湧かない。CPU基板の上にのせる液晶、SDカードソケットなどを載せるサブ基板のレイアウトがなかなか気に入った構成にならない。モジュラージャックは、べたアースの基板を使いたいが、そうすると基板が三重になってみっともないしと、あれこれ迷っているだけである。

 で、相変わらず、また脱線してしまった。タイマーの実装である。経過時間を示す1ms単位のTickタイマーは、USBの新バージョンでsystickを使われてしまって動かなくなっている。ちょうど良い機会だ。今まで面倒なのでやってこなかったSTM32のタイマー実装に挑戦してみた。予想通りこれがどうして、手ごわかった。

Stm32

 弁護士さんの書いた参考書「STM32マイコン徹底入門」は、このあたりが100ページ近くにわたって詳細に紹介されていて、なかなか役に立つが、それにしても設定パラメーターが恐ろしく多い。とても最初からやってられない。結局、自分でいちから書くのをやめ、ひとさまのソースを拝借して、0.5秒のタイマーを作った。

 ソースの丸写しである。LEDチカチカで成功を確認する。単純なオーバーフロー割り込みのタイマーだけで16行の定義である。いやあ、これは大変だ。まあそれだけ機能が多いということなのだが、どうみても入門者には無理だ。

 しかし動かしてみると、USB仮想UARTがタイマーで字化けする。本来あってはならない状態なのだが、理由がわからない。このあたりでその日の気力を使い果たした。
何かの参考になるかと思い、コード例をお示しする。

void TIM2_start(void)
{
NVIC_InitTypeDef NVIC_InitStructure;    //割り込みベクタのインスタンス定義
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //タイマー定義構造体
TIM_OCInitTypeDef TIM_OCInitStructure;  //コンペアマッチ構造体(今回不使用)

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //クロックを起動

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;      //TIM2割り込み定義
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);         //割り込みベクターの初期化

TIM_TimeBaseStructure.TIM_Period = 14280-1;    // カウンターの上限値
TIM_TimeBaseStructure.TIM_Prescaler =360-1; //プリスケーラー値
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //キャプチャークロック分周
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //増加カウント

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //上記定数でタイマーを設定

TIM_PrescalerConfig(TIM2, 4,TIM_PSCReloadMode_Immediate);//プリスケール再設定

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  //上限値で割り込み許可;

これは設定だけで、このほかに割り込みハンドラーのコーディングがある(略)。
オリジナルは、ここのページである。
(TIM_PrescalerConfig()は不要でした。12/2/2014 修正)

S_p1314617


ダブルバッファーにしてSTM32F107の仮想UART端末完動(2/4/2012)

 V3の仮想COMデモをベースにしたUART仮想モニターは動いたとはいえ、データは欠落するし、たまにハングし、まだ使い物にはならない。もともとソースがひどく読みにくかったので、リングバッファーを使った処理に殆どの部分を書き換え、見通しが良くなったのだが、どうにも安定しない。Sof_

 タイマーを入れて文字化けする問題は、タイマー割り込みが計算違いでマイクロ秒単位で起きていたことがわかり、1ms単位になるようにして解決したが、不安定なことは変わらない。

 こうなると意地である。ロジアナを持ち出して、本格的なデバッグ体制に入った。基板についているLED、2 ヶをロジアナのプローブ点にして、各ルーチンの動きを探る。USBの資料も読み直して、ロジックを勉強しなおす。

 STM32のUSBライブラリは、V3でUSBホストにもなるOTG機能がついた。このためにUSB制御の階層がさらに増え、エンドポイントのバッファー操作が直接出来なくなっている。そのため、このV3のVCOMでは、データ送信のキックは、送信エンドポイント(USBにとってはIN方向)の書き込み後の割り込み(EP1_IN_Callback)ではなく、USBの定期的な割り込み、SOF割り込みで行われるようになっている。

 このため、マイコンの中での送信要求は、このSOF割り込みがms単位と長いので、実際にUSBを通してPC側に送られるデータが多量に溜め込まれて待たされることになる。片側がUARTならそう問題ないが、マイコンの中の送信要求は、べらぼうに早いので、これがハングやデータ欠落の原因になっているようだ。

 未送信のデータでバッファーが一杯になれば、マイコン側の送り込みを待たせ、そこからエンドポイントバッファーに書き込んでいくロジックになってはいるが、この多重処理をしているうちに、ハングアップしてしまうようだ。

 だいたい、この新しいSTマイクロのエンドポイント書き込み関数SIL_WRITE()は、パケットサイズの64バイトまでフルにデータを入れて、エンドポイントに立て続けに書き込むと、それだけで確実にフリーズする(半分くらいだと大体大丈夫)。どうも下位ルーチンがバグを抱えているようだ。恐らくエンドポイントの処理中に入るハード割り込みを止めていないのでレジスターが壊されているのだろう。

 思い切って、このV3のやりかたを捨て、前に成功しているダブルバッファー方式に換えることにした。この方式は、ユーザーの送信要求をパケットサイズ単位で待たせることになるので、USB側に多くの負担をかけることがない。SOF割り込みは使わない。最初のキックは、前と同じように、片側のバッファーでダミーデータの空打ちをする。

Photo

 V1のコードを丸々、こちらに引き込む。大した作業量ではない。ビルドする。おお、フラッシュサイズも4KB以上小さくなった。ファームを書き込む。さあ、どうだ。動くか。よーし、オープニングメッセージが出た。エコーバックも大丈夫なようだ。次は問題の大量メッセージ送信である。

 まずは、1000バイト。問題ない。次は、2000バイト。オリジナルのVCOMでは滅多に成功しない量だ。問題ない。いいぞ、いいぞ、送信量を増やして行く。遂に13KB(リターンキーだけだとx0Dで13)でも全くハングもデータ欠落もなく画面に出力が表示された。速度は前と同じ2Mbps(前のV3オリジナルでは、とりあえずすべて受け入れるので4Mbps以上だったが、動かないことには意味がない)。

 なーんだ。最初から、このダブルバッファー方式にして置けば良かったのだ。久しぶりに解決したときの興奮を味わう。やっぱりこれが味わえないと電子工作らしくないな。気分が良くなったところでブログに報告することにする。

Vcom

 以下に、Eclipseのプロジェクトフォルダーとして入ったソースコード一式のzipファイルを置きます。STマイクロV3のペリフェラルとUSBライブラリは、5MB近くあって、このブログの容量制限で載せられないので、正規サイトなどで落とし、フォルダー名を上記プロジェクトフォルダー直下のlibとして下さい(um0424のSTM32_USB-FS-Device_Lib_V3.3.0内にあります) 

詳しくは、同梱のmakefile参照。ねむいさんのソースから変更したのは、main.c usb_endp.c hwconfig.cの3本だけです。

「pub_STM32_VCOM3.zip」をダウンロード

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

« 2012年1月 | トップページ | 2012年3月 »