RTL8196CのBare MetalでlwIPを使えるようしてみました。NICのコードはlwIPのテンプレート(ethernetif.c)に埋め込み、Switchのコードはbootのコードをそのまま利用しました。
Switchのコードはifdefやコメントアウトが錯綜していてとてもひどいコードです。チップのバージョン毎の仕様の違いやバグがそうしているようです。
当初自分が書いたNICのコードのバッファサイズの指定が抜けていて送信が出来ない状態でしたが、これを設定して送受信ができるようになりました。
NICの実装はシンプルにTX,RXとも1リング4段で実装しました。
ところが、シリアルケーブルを抜くとネットワークが機能しなくなります。
いろいろ調べたところシリアルのRXがつながれていないとNIC送信が出来なくなるようです。
bootのコードを確認したり、linuxのコードを確認したのですが、理由がわかりません。そもそもNICとUARTは別のデバイスなのになぜ干渉するのでしょうか。
電気的にプルアップしたりプルダウンしてもだめでした。
半分あきらめかけたのですが、朝うとうとしていたときにオリジナルのコードを思い出しました。
//avoid download bin checksum error
uint32 rx[6] = {4, 0, 0, 0, 0, 0};
uint32 tx[2] = {4, 2};
/* Initialize NIC module */
if (swNic_init(rx, 4, tx, MBUF_LEN)) {
dprintf("¥nSwitch nic initialization failed!¥n");
return;
}
rx,txはリングのバッファ数なのですが、rxは1本なのに何故かtxは2本になっています。それも何故か4と2。bootのネットワーク処理はtftpでバイナリを受け取るだけのはずなので、txの方が多いのは解せません。
これが秘伝のたれでした。同じようにしたところシリアルを外してもネットワークが使えるようになりました。
bootのNICのコードはlinuxのコードを流用したようですが、bootを作った人も同じようにはまったのかもしれません。
RTL8196CなどのネットワークのコードはREALTEKのboot(boot/rtl8196x)とlinuxのコード(drivers/net/rtl819x)とOpenWRTにあります。OpenWRTのものはrealsil(関係会社?)の人が結構頑張って整理しています。
ちなみにRTL8196Cにはレビジョンが二つあって、私のターゲットは2だったのですが、1の方のレビジョン用に結構やばそうなワークアラウンドがbootのNICのコードに入っています。
REALTEKの最初のmips系のsocはRTL8181だとおもうのですが、これにはSwitchが入っていませんでした。バッファもTulipライクな32Bit×4な構成だったようです。どうも蟹さんは必要以上に複雑にしてしまう感じがします。
まったくもって蟹です。
ソースはここに置いてあります。
後日追記:いろいろいじっていて、受信のリストを二つにしていたのですが、夏の間は動いていたのですが、年末になったら調子が悪くなったので、bootと同じように一本にしました。ほんと蟹さんは分けの分からん動きをします。