内容の正確さについては保障ができません。 参考にされる場合にはどうか自己責任で行ってください。 よろしくお願いします。
大容量RAMを搭載したネットワーク接続可能なマイコンボードを開発した。 大容量RAMとして16MByteのSDRAMを搭載し、MCUとしてNXP社のLPC2468を用いた。 RTOSを暫定的に動かすまでをまとめる。
MCUをEthernetにつなぐことで、インターネットから情報を取得しMCUで情報を加工して表示したり、 遠隔からMCUを操作することが可能になり、あたらしい電子工作の世界がひろがりつつあります。
しかしながら、現在の一般的なMCUが内蔵するRAMの容量は小さく、 インターネット等から情報を収集するような処理を行うにはRAM容量が不足する問題点があります。 そこで、 Ethernetに接続可能でとにかく大きなRAMを持ったマイコンボードを設計することにしました。 このボードを以前設計したNetwork Appliance 2の後継にしようと考えています(Network Appliance 3 計画)。
現状、RTOSを動かし、Shoutcastタイプのインターネットラジオを受信し、再生できるところまで 確認しました。 右図が、再生中の様子。 インターネットラジオの再生においては、一般的に、音が途切れにくくするために 数十キロバイトから数百キロバイト程度のメモリ領域を用意し、 ネットワークからの受信データのバッファリングに用います。 製作したボードは大容量のRAMを搭載しているため、十分なバッファ領域を用意することができ、さらに液晶画面の表示もできています。 しかし、 このような応用はMCU内蔵のRAMだけで実現しようとすると、困難なものになります。
MCUの選択においては、手で実装することを考えるとパッケージがQFPである必要があって、機能的な要求から SDRAMのコントローラとEthernetコントローラを搭載していることが必要でした。 これらの点を満たし、なおかつすぐに入手できるMCUをリストアップし、 その中からNXPのLPC2468をえらびました。 Luminary micro のLM3S9B00シリーズが本命だったのですが、入手できませんでした。
プリント回路基板(PCB)は マレーシアの業者に依頼して製作してもらいました。発注から10日程度で届きました。 仕様はFR-4の2層基板、片面シルク印刷で、8枚で注文したらなぜか9枚届いて約80米ドルでした。
ディスプレイには河原温の日付絵画的なものを表示してみた。
LPC2468基板の表面。QFP208のはんだ付けは難しそうに見えて、それほど困難ではないと思います。 熱が分散しやすいので、半田ごては高出力なものがよいと思います。フラックスも必要です。 放熱性を高めることを考えてベタが広めなのもありますが、30W程度の半田ごて(goot CXR-41)では不十分でした。 温度調節機能付きの70Wの半田ごて(goot PX-201)を使いました。
チップを取り外すためのキットを各社販売しているので手元に置いておくとはんだ付けに失敗したときに役立ちます。 Chipquick SMD1というキットを使ったことがあります。ただ、このようなキットを用いても上手く救済できない事もあるので、 はんだ付けをするときには難易度と失敗による被害を考慮して順番を決めるといいと思います (難易度の高いものはできるだけ始めの方に、高価な部品はできるだけ後回しにする。作業に取りかかる前に手順を決めておく必要があります)。
あまり器用ではないので一台分のはんだ付けと動作確認(はんだ付け作業の各段階でも行う)で約一日かかります。
LPC2468基板の裏面。FPCのためのコネクタ(OMRON XF2L-3025-1)のはんだ付けは難しいです。 "Slide-locking Connector"なのですが、はんだをつけ過ぎるとスライドしなくなります。 また、脆いのでFPCを差し込む際に力むとスライドを壊します。
USBホスト部を除いたほぼ全体が3.3Vで動いています。 チップの最大消費電流を単純に積み上げていくとMCUとSDRAMとEthernet PHYチップだけで500mA程度になりそうでした。 そのため、ACアダプタからの入力(5V)から3.3Vを生成する部分では安全を見て出力を1.5Aとれる設計にしています。また、放熱で問題を起こしそうだったのでシリーズレギュレータではなくて スイッチングレギュレータ(LM2831XMF)を使い、熱伝導をよくするために裏表のベタの面をできるだけ残すように配線を通しています。 ただ、実際に使ってみると、PHYチップが多少熱をもつ程度で想定したほど電流は流れていないようです。 テスター(SANWA CD721)を用いて、ACアダプタ(5V出力)が供給する電流を簡易的に計測したところ次のような結果が得られました (いずれ場合についてもUSBデバイスは接続せず、CPUコアは72MHzで動かし、周辺回路のクロック分周比はUSBを除いてデフォルトのままとしています)。
LAN無接続時 | 約180 mA |
LAN接続時(100Mbps) | 約230 mA |
LAN接続(100Mbps)・ネットラジオ(64kbps)再生時 | 約240 mA |
SDRAMとMCUの間で72MHzの比較的高速な信号が通っています。 高速な信号を通す場合、信号の反射やクロストークが問題になるといわれていますが、 このくらいの周波数なら、配線を短くするように気をつければ大丈夫そうです。 抵抗を入れるなどの対策はしていないですが今のところ問題なく動作しています。 ノイズの問題も気にかかりますが、これはアマチュアには対応が難しいところです。
Ethernetコントローラ付きMCUは各社から出ていますが、UARTやSPIほど単純な周辺回路ではないので、
性能や使い勝手に差がある可能性があります。
ヘビーに使う場合、事前にデータシートで比較したり情報収集が必要かもしれません。
たとえば、単純比較は難しいですがEthernet用のDMAのありなしで比較してみると、
LPC24xxやST社のSTM32のConnectivity line devices だとDMAをもちますが、
TI(Luminary micro)の少し古めの LM3S6965だとDMAが無いようです。
そのため、LM3S6965はスピードが必要な場面では若干不利になる可能性があります
(最近のLM3S9BxxではDMAが追加されています)。
そのほかの観点からみると、
LM3S69xx, LM3S9BxxにはEthernet PHYがMCUに内蔵されていて外部にPHYチップが不要です。
そのため、コストを削減でき、ボード設計もやや容易になります。
STM32のEthernet MAC は Synopsys の DesignWare のIPを使っているようなので、
DesignWare のEthernrt MAC IPを使ったASICや他社のMCU(もし存在すれば)にもソフトウエアを再利用できる可能性があります。
MCUの性能は、クロック周波数やCPUコアだけではなく、内蔵フラッシュメモリのスピードやMCU内のバスの構成にも依存します。 たとえば、比較的高いクロック周波数(数十MHz以上)でMCUを動かす場合、 品種によってはMCU内部のフラッシュメモリの読み出しが命令実行のスピードに追い付かない場合があり、 これがボトルネックになる場合があります。 LPC24xxの場合、フラッシュメモリのアクセラレータ(MAM)を用意し、 低速な内蔵フラッシュメモリ(クロック周波数が72MHzの場合、一度のアクセスに4クロックサイクル必要)と CPUコアのスピード差を埋めるられるように設計されています(ただし、分岐時には若干のペナルティがあります)。 また、DMAを使う場合(バスマスタが複数ある場合)では、バスの取り合いが起きる可能性があるので、 バスの構成がシステムの性能に与える影響が大きくなります。 したがって、MCUの選択には内蔵フラッシュメモリのスピードやバスの構成も考慮する必要があります。
MP3形式の音声を再生するためにMP3デコーダチップを搭載しています。 ソフトウエアでデコードすることも考えたのですが、 通信処理などで時間を取られることが考えられたので専用のチップを載せることにしました。
LPC2468にはSDカードインタフェース回路がついていますが、今回は使っていません。 コネクタは全て基板の右端と左端にかためているのですが、 SDカードスロットは比較的面積を取るので配置が難しそうでした。 USBホスト機能があればUSBメモリが使えるので、SDカードスロットは省きました。
PCBを格納する筐体はアクリル板で作っています。設計に当たってはGoogle SketchUpを使っています。 細かい数字をいじるには向いていない感じがするのですが、それらしい見た目のものができます。 デザインを決めるのによいとおもいます。
2台製作して、一方はMCUにLPC2468、他方はLPC2478を使用しています。 LPC2478はLPC2468にLCDコントローラがついたタイプで、若干高くなるのですが、入手の関係で使用しています。 今回使用したLCDモジュールにはコントローラが入っているのですが、 次回はLPC2478を使って、MCU内のコントローラを利用してQVGAくらいのカラー液晶を使いたいです。
ご自由にお使いください。お約束ですが「無保証」です。 趣味の工作で作ったものなので、参考程度と考えて利用することを強くお勧めします。
現在、FreeRTOSとTCP/IPプロトコル・スタックlwIPを用いてShoutcastのインターネットラジオを受信できるところまでたどり着いたところです。 プロトコルスタックとしてuIPを用いるとネットワークプログラムを書くのが大変でしたが、lwIPをRTOSと使うと大分緩和されます (lwIPの機能をすべて使うにはRTOSが必要)。
今回FreeRTOSとlwIPを用いた理由は、ネットワークプログラムが書きやすいのも一つですが、 移植の手間が一番少なくて済みそうだったという点が大きいです。 別の組み合わせもあるので(TOPPERSとTINETの組み合わせなど) 後で変更するかもしれません。
図はボードで動いているWebサーバーにアクセスして画面キャプチャしたものです。
図中背景: 奈良美智、「あおもり犬」、青森県立美術館、個人撮影。
今回使ったMCUのCPUコア(ARM7TDMI)だと wordを4の倍数の番地、half-wordを2の倍数の番地に置かないと上手くアクセスできません。 ネットワークから受信したデータをpackした構造体として扱う時に問題が起きやすいと思います。 ちなみに、最近のARM CortexM3コアではこのような制約はなくなっています。
CodeSourcery の gcc 4.4.1 (Sourcery G++ Lite 2009q3-68)でコンパイラのバグに遭遇しました。 ここ(gcc-bugs@gcc.gnu.orgのアーカイブ内の"Bug c/41999")の症状そのままです。 アセンブリレベルで見ないと分からない問題だったので発見に時間がかかりました。 このバージョンのCodeSourcery の gcc を使う場合には注意がいると思います。
USBホスト機能、Ethernetコントローラ、SDRAMコントローラについて、それぞれ USBHostLite(Application Note(AN)10703), AN10799, AN10771にサンプルコードが付属しています。 USBホスト(USBメモリへのアクセス)、SDRAMコントローラのコードはそれほど書き換えなくても済みました。 ただ、EthernetコントローラのサンプルコードはプロトコルスタックとしてuIPを使っているので、 uIPを使う場合にはよいのですが、lwIPを使うときには書き換えが必要でした。
SDRAMとMCUがしっかりと接続しているかを確かめるために、LFSRで疑似乱数を作って全体に書き込んでから、読み出してみて、 書き込んだ値と一致しているかどうかをみました。 この操作を3回(byte, half-word, word単位で読み書き)して動作を確認しました。
MCUの内蔵SRAMをどの機能に優先的に割り当てるかについては検討が必要です。 SDRAMは内蔵SRAMと比較すると若干遅いので、スピードが特に求められる箇所では利用を避けるのが無難です。 簡易的な実験として次のプログラムをスタックとバッファ (プログラム中のbuf) の位置をさまざまに変えて実行したところ、
void speedtest(volatile int *buf){ int i; volatile int *t = buf + 50; volatile int k; for(i=20000000; i!=0; i--){ k = *(buf) + *(t); } }
また、プログラムを内蔵SRAMに置くことも高速化の面で有効です。 これは、フラッシュメモリのアクセラレータ(MAM)を用いても、プログラムの分岐時などでペナルティがあるためです。 上で示したプログラムを内蔵SRAMに配置して実行したところ次のような結果になりました。
lwIPにはシステムの規模に応じて、RAW層、NETCONN層、SOCKETS層の3つの層のAPIがあります。 NETCONN層より上を使うためにはOSが必要になってきます。 今回はNETCONN層のAPIを使ってプログラムを書いています。 NETCONN層のAPIでは、netconn_recv()を使って得たnetbuf構造体からnetbuf_data()で 受信データを取り出せるのですが、netbuf構造体の内部にリストを持っており、 netbuf_next()を使って残りデータの有無を確認しないとデータを取りこぼすことがあります。 これが原因で、インターネットラジオの再生時に間欠的な音飛びを引き起こし、原因特定に手間取りました。
lwIPのソースコード中で定義される TCP_SND_BUF と TCP_WND の値は送受信スピードに大きな影響を及ぼします。 インターネットラジオ程度の通信でも TCP_WND の値が小さいと十分な受信スピードが得られず音飛びが生じました。 少なくとも 2*TCP_MSS 程度は用意しておかないといけないようです。 また、TCP_SND_BUF の値が小さいと送信スピードが出ない症状が表れるので、 Webサーバなどを書く際には気をつけないといけません。Delayed acknowledge に起因する問題のようです。 4*TCP_MSS 程度にすることで症状がおさまるようです。
FreeRTOSとlwIPを移植したものをここに置きます。 使いやすくするために、最小限の部分だけを切り出したものになっています。 次の点に注意すればLPC24xxならほぼそのまま使えると思います。 FreeRTOSのAtmel AT91SAM7用のデモ(lwIP_Demo_Rowley_ARM7)などをベースにして、 NXPのApplication note AN10799 のコードを部分的に使用して組んでいます。
FreeRTOS 6.0.1をダウンロードし、適当な場所で展開します。 FreeRTOS/Demoディレクトリの下に、適当なディレクトリを作り、そのディレクトリの中で下のファイルを展開します。 makefileの位置は FreeRTOS/Demo/xxxxx/FreeRTOS6.0.1_lwIP1.3.1_LPC24xx_minimum.20091228/makefile になります(xxxxxが作ったディレクトリ)。 コンパイルはmakefileがあるディレクトリでmakeすることでできます。 開発に使用したコンパイラは gcc 4.2.2 (yagarto 20091018)です。
無保証です。また、メールをいただいても個別の問題に対しては基本的に返事はしていません (あまり返事を期待しないでください)。
追記
コンパイラのバージョンによっては、コンパイル時に"Error: missing expression --swi"となりコンパイルができないことがあります。
これは、FreeRTOS/Source/portable/GCC/ARM7_LPC23xx/portmacro.h の portYIELD() の定義を
#define portYIELD() __asm volatile ( "SWI 0" )とすることで回避できました(コンパイラのバージョン gcc version 4.4.1 (Sourcery G++ Lite 2010q1-188))。
NXP社のMCUであるLPC2468を用い、大容量のRAMを備えたボードを設計しました。 FreeRTOSを暫定的に移植し、TCP/IPプロトコルスタックであるlwIPも含めて動くことを確認しました。 Shoutcastタイプのインターネットラジオ機能を実装し、 受信・再生ができることを確認しました。
この基板を使った応用例に、「Network Appliance 3 計画」があります。
これまで日本語のみでページを作ってきたのですが、 これからは英語のページも必要と思われるので適宜翻訳していこうと思います。 英語が得意とは言い難いのですが...
(2009/12/13)
(2009/12/30改訂)
(2010/2/18改訂)
(2010/3/6改訂)
(2010/3/27改訂)
(2010/4/14改訂)
(2010/4/25改訂)
(2010/7/5改訂)
(2010/10/6-8改訂)
(2011/3/13-14改訂)
(2011/5/3改訂)
(2011/12/12改訂, ページタイトルの変更とLM3S9B96ボード(model 2)へのリンクの追加)