Jul 19, 2006
AVR uIP on ATmega128
Optimize氏のSPIイーサネットモジュールを入手したので、遊んでみた。まずはお手本どおりmega168でやってみたものの、メモリが少なすぎて面白くないので、買ったまま放置してあったmega128にメモリ増設をして再挑戦。
ベースをuIP0.6からuIP0.9に変更し、Webサーバのサンプルを動作させることが目標。
uIPの使い方自体が非常に簡単なのと、すでにENC28J60のドライバがあるので、ビルドはすんなりと出来た。
しかし、ブラウザからアクセスしてみると応答なし。pingの応答はあるので、動作しているはず。
仕方がないので、Wireshark(旧ethereal)にてパケットキャプチャとデバッグコードを埋め込んでシリアルポートからモニタリングを実施。
perlスクリプトからリクエストを投げて実験してみると、パケットサイズが240バイト位までであれば応答を返すことが判明。それ以上だと、ACKすら返さないので、送信側が再送を繰り返していた。
結局はenc28j60.hに定義してあったMAX_FRAMELEN(イーサネットフレーム長)が300に設定されていることが原因。これを1518に設定することで解決。
さて、これで何を作るかな。
ATmega128と増設メモリ
SPIイーサネットモジュールで遊ぶために、ATmega128にメモリ増設をしてみる。データシートによれば、データバスとアドレスバスの下位8bitは共通で、ラッチを使って実装せよとのこと。AVRは高速に動作するため、74HCシリーズでは遅くて使えないよという注記あり。
そもそも、手元にあるメモリで16MHz(62.5ns)でアクセスできるものもほとんど無いなあと思ってパーツボックスを物色していると、486マザーに搭載されていた2次キャッシュ用SRAM(15ns)を発見。容量も丁度512kbit(64KB)。とっておいて良かった。
で、ラッチは74VHC573を購入。これならば5nsで動作可能なので問題なし。
回路が決まれば、あとは淡々と半田付け。せっかく多ピンのAVRなのにメモリ接続に食われる(19pin!!)とほとんど使えないのね。
さて動作確認という段階でライタで認識されないという問題に直面。配線間違いなのかとためしにJTAG接続でIDCODEやらシグネチャバイトやらを取得すると正常に動作している模様。
データシートをもう一度見直していると、なんとmega128はISP用のピンがSPIではなく、PD0/PD1を使うとの記述が。今まで使っていたAVRは皆SPIと共用だったので、なんの疑いも持たずに配線していたが、ちゃんと確認しないとイカンですね(フューズビットの出荷時の状態ではmega103互換モードというところは気付いて注意していたんだけどね)。
配線を直して、メモリチェック用プログラムを稼動。問題無いことを確認。
ハードが完成したので、次はソフト。uIPで遊ぶことにしたが、ここでまたしても問題発生。アセンブラで書いていたときには問題なかったXMEMのハンドリングがCでは困難に。
具体的には、
- dataセクションの開始アドレスの設定方法がわからない。
- スタートアップルーチン内で、プログラムメモリからデータメモリへの転送がされるため、それより前にXMEMを有効化しなければならない。
1点目は、gccの引数でldのオプションが指定出来るので、これを利用し、"-Wl,-Tdata,0x801100"としてみるが、gccが先に標準値を指定してしまうため、効かない。(ldは同じオプションを複数指定した場合、最後に指定したオプションを生かすのではなく、無視してしまう)
仕方が無いので、gccに頼らず、ldを直接起動して必要な引数を指定することで回避した。
2点目は、スタートアップルーチンのソースを修正し、データコピーをする前にXMEMを有効化するようにした。
(ちなみに、スタートアップルーチンのソースはavr-libcに含まれるので、これを展開すれば入手可能)
小規模組み込み環境でもCでプログラムを書けるようになったのは良いことなんだけれども、小回り効かすのは大変ですな。