今頃LPC2388基板(CQ-FRK-NXPARM)とかいぢってみる

2x歳も半ばを過ぎて、やっとクレジットカードを手にしました…
磁気カード式の定期使うためには半ば強制加入だったもんで仕方無く導入なん
ですけどね〜。案の定早速パスワード失念しかけて青くなる私。






CQ誌のインターフェース誌や今は亡きDWM誌は春になるとARM系のマイコン基板
が付録に付きます(ました)ね。フレッシャーズ向けとの触れ込みですが、これ系の
基板は通電前に回路図、部品データシートをよ〜〜〜〜く観て吟味した上で
遊ばないといけないのは周知の事実だと思います。

また、記事もゲーメスト並に豪快な誤植・間違いが多いので鵜呑みにしてしまうと、
マイコン初心者の方向けのEASYな難易度のはずがSUPERHARDのハマリ地獄に
直行したり知らぬうちに基板壊すなんてことも多々あります。
(「ザンギュラのスーパーウリアッ上」レベルなら笑って許せるけど+5Vと+3.3V
間違えるとかはヤバ過ぎだ)

幸いなことに現在はブログ等で情報の相互のやりとりができるのでホビーで楽しまれ
ている方でも出来るだけ損をしないように十分調査をした上で実験・製作等をする
のが良いと思います。ググるだけでも全然違いますからね。
ねむいさん的には危険と失敗のリスクを隣り合わせにするのも遊びの醍醐味と
思ってるので
付録基板の企画はこれからも支持したいと思います(性的な意味で)。


また前振り長くなりましたが、私もARM7TDMIのアーキテクチャ学習用にこの基板を
いぢっています。雑誌記事のチュートリアルは全てガン無視でMartin THOMAS氏の
LPC2378のサンプルをベースにLPC2388(CQ-FRK-NXPARM)向けにコードを移植、また
リンカスクリプト、スタートアップコードもnewlibのprintf系の関数が使用できる
ように試行錯誤を繰りかえして徐々に付け足していきました。
以下にARMをGCCでコンパイルする際、newlib(標準Cライブラリ)のprintf系関数
をハングしないように使うための最低限のコツとかを。
注:CodeSourcery/RaisonanceRIDE7の環境下でのコンパイルを想定してます。

1.システムコール関数群を定義する。
 syscalls.cというファイルにprintf系の関数を使用したときに呼び出される
 関数群を定義するのが通例となっています。定義してないとリンク段階で
 「sbrkr.c:(.text+0xc): undefined reference to `_sbrk'」とかのエラーが
 出てきてしまいます。
20110912改変:
 AVRやPICで慣れた人がSTM32やLPC2000/1000などのARMマイコンを初めて使用
 する際に必ず引っかかるポイントですが、CodesourceryG++などのGNUなビルド環境
 ではprintf等の関数の出力先を柔軟にするために_readや_write,_sbrk等のローレベ
 ル関数が実装されていないので自前で作ってやる必要があります。
 sourceware.orgにsyscallについての簡単な解説がありますので参照してください。

 printfを出力を吐かす先はたいていはシリアル出力となるので_readや_write関数
 については自前のシリアルの一文字入/出力関数をリターゲットしてやればよいです。
 上記URLに則すならたとえば_write関数のoutbyte(・・・の部分を自前のUART出力関数
 に置き換えればリターゲットは実現できることになります。

 _sbrkについてはprintf系関数(書式に変数を含まない場合に限りmemcpyが呼び出さ
 れるもようです)やmallocを使用する際にメモリアロケーターのローレベル部として
 後述の外部変数_endと絡めて呼び出される極めて重要な関数です。

 audin氏も(話がOSにも絡んでいますが)非常に深い考察をされていますので必読です!


2.リンカ・スクリプト内の_endの定義
 newlibは_sbrkという関数で_endを参照してきますので、リンカスクリプト内で
 外部変数_endを定義します。調べた限りではbss領域の直後でheap領域の初めに
 (heap領域がリンカスクリプト内で明示されてないのもあるが…。)
 定義されていますのでそう記述しておきます。

3.スタック領域の確保
 printf系の関数はスタックをびしばし使って1kバイト近く消費しますので、
 printf系の関数使う場合1kbyte以上+本来使用するスタックのバイト数を定義
 しときます。確保してなくてもパッと見ちゃんと動く時もあるので結構見落とされ
 がちです。動作が怪しい時は、スタックの確保量を疑ってみてください。
 Martin THOMAS氏のサンプルとそれを真似した私のソースはスタートアップ
 ルーチン内でスタック領域の確保を行っています。
 また、可変引数に変数がない純粋な文字列のみの場合、printf関数はコンパイラ
 側で自動的にputs関数に切り替えられます。

4.printfとか使うとリンクされる「.ARM.exidx」セクション
 WINARM20060606にはこんなのなかったはずですが…、ググりまくって調べると
 こことかここに詳しく説明がありました。
 arm-(OS名)-eabiな処理系でnewlibとか使うと無理やり挿入されちゃうようです。
 .ARM.exidxもリンカスクリプト内で適切に定義してやらないとリンク時エラー
 になったり「sh_link not set for section `.ARM.exidx'」ってワーニング
 吐かれたり、コードサイズが異様に膨れ上がったりしますのでやや注意です。
 私の環境では上記の様に配置して無難におさまってもらってます。


以上の点を踏まえ、printf/sprintf使用してUARTにRTCの時刻情報を吐く
CQ-FRK-NXPARM向けのプログラムをこしらえました。32.768kHzの水晶必須です。
おまけで#defineでscanfを使用した簡易メモリダンプに切り替えられるようにしてます。
ダンプのルーチンはSYSLAB氏が公開されていた物を使用させていただきました。
ソースはこちらに。自己責任でどうぞ。
フラッシュの書き込みができるlpc2388用のopenocdバイナリもついでに。


RTC用のVbatは基板上でVccに直結されていますが切り離してやると本来の動作が
できるようになります。今、バックアップ電池でARM基板のRTCを動かすのが
流行ってるようなので私も真似して付けてみました回路構成はこんな感じです
今回使用したTAKACHIのCH7410-2032LFというボタン電池ボックスはコンパクトで
底が平らなため、CPUの上に両面テープでペタッと置けるので重宝してます。



Go to top of page