先日、ping が通るようになったネット・スタックだが、その先が中々進ま
ない。
苦労して、デバッグをした結果、ようやく、動作するようになった。
・ルネサスの、「r_socket_rx」にバグがあった。
※アドレス構造体にポートを設定する部分は、ソケットの仕様では、ネット
エンディアン(ビッグエンディアン)で行うのだが、それが逆だった。
・「r_t4_rx」のチェックサム計算ソースに問題があった。
※このアセンブラソースは、ルネサスの統合環境向けのソースコードで、
「gcc」の場合、アセンブルは通るが、そのままでは正しく動作しないよ
うだ。(これが判るまで、非常に苦労した)
.file "cksum_rx_little.s" .section .text.ck .global __cksum __cksum: ; function: _cksum ;uint16 _cksum(uchar *data, uint16 nbytes, uint16 sum0); and #0ffffh, r2 ;arg2 uint16 and #0ffffh, r3 ;arg3 uint16
上記のように、少し修正した。
次に、ソケット関連だが、ソースコードを見ると、ノンブロックモードが
用意されているようだが、実際はこのモードはまともに動作しない事が判
った。(とりあえず、ブロックモードで行っている)
ソケットのモジュールでは、BSDソケットとの互換を意識して、関数名
や、構造体を同じにしているが、これが、オリジナル(POSIX)のソケット
関係と当るので、それに準じた、名称に変更した。
これらを修正し、以前に実装した、Arduino 系のプログラムをソケット系に
修正を加え、http_server クラスを新規にコミットした。
また、元のネットスタック関係をデバッグ中、色々問題がある部分が多く、
それらに修正を加えた、なので、オリジナルソースとは違うものになってい
る。
・ソースの色々な部分で、「extern」を使い、変数の型や、関数の型を宣言
しているが、一つのソースで共有すべきなので、新たに、「global.h、
global.c、config_tcpudp.h」を作成した。
※まだ、みるに絶えない部分は沢山あるが、とりあえず・・・
ネットスタック全体は以下のような構成になっている。
ip_adrs.hpp dhcp_client.hpp net_tools.hpp net_core.hpp socket.hpp http_server.hpp r_tcpip_private.[hc] r_config/r_t4_rx_config.h r_config/r_socket_rx_config.h r_t4_rx/src/config_tcpudp.[hc] r_t4_rx/T4_src/dhcp.[hc] r_t4_rx/T4_src/ether.[hc] r_t4_rx/T4_src/global.[hc] r_t4_rx/T4_src/igmp.[hc] r_t4_rx/T4_src/ip.[hc] r_t4_rx/T4_src/r_t4_itcpip.h r_t4_rx/T4_src/t4define.h r_t4_rx/T4_src/tcp.[hc] r_t4_rx/T4_src/tcp_api.c r_t4_rx/T4_src/type.h r_t4_rx/T4_src/udp.[hc] r_t4_rx/T4_src/checksum/rx/cksum_rx_little.s
インサーネットのハードウェアーの定義は以下のようにする。
typedef device::ETHERC0 ETHERC; // Ethernet Controller typedef device::EDMAC0 EDMAC; // Ethernet DMA Controller typedef chip::phy_base<ETHERC> PHY; // Ethernet PHY typedef device::ether_io<ETHERC, EDMAC, PHY> ETHER_IO; ETHER_IO ether_; typedef net::net_core<ETHER_IO> NET_CORE; NET_CORE net_(ether_); typedef net::http_server<ETHER_IO, SDC> HTTP; HTTP http_(ether_, sdc_);
※PHY 層デバイスは、GR-KAEDE に使っている、Microchip LAN8720 用だが、
PHY 層デバイスは共通部分が多いので、そのまま使える、他のデバイス用に
カスタムする場合、「phy_base.hpp」を参考にして別のデバイス用を作成す
る。
※「SDC」は、SDカードの操作を行うクラス。(「main.cpp」参照)
※他に、ルネサスのネットスタックとの仕様を合わせるCの関数を定義する。
(ソースコード「main.cpp」を参照)
メインプログラムからHTTPサーバーを使う場合、以下のようにすれば良
い。
※「/」ルートページのレンダリング定義は、サンプルでは動的なプログラム
で行う。(C++ではラムダ式が使えるので簡潔に書ける)
{ // Ethernet の開始 ether_.set_intr_task(lan_inthdr); uint8_t intr_level = 4; ether_.start(intr_level); static uint8_t mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; net_.start(mac); } { // HTTP サーバーの設定 http_.start("GR-KAEDE_net HTTP Server"); // ルート・ページ設定 http_.set_link("/", "", [=](void) { time_t t = get_time(); struct tm *m = localtime(&t); HTTP::http_format("%s %s %d %02d:%02d:%02d %4d
\n") % get_wday(m->tm_wday) % get_mon(m->tm_mon) % static_cast(m->tm_mday) % static_cast (m->tm_hour) % static_cast (m->tm_min) % static_cast (m->tm_sec) % static_cast (m->tm_year + 1900); http_.tag_hr(500, 3); } ); } uint32_t cnt = 0; while(1) { // 100Hz (10ms interval) cmt_.sync(); sdc_.service(); net_.service(); bool l = net_.check_link(); if(l) { http_.service(); } device::PORTC::PDR.B0 = 1; // output LED port device::PORTC::PODR.B0 = (cnt < 10) ? 0 : 1; ++cnt; if(cnt >= 50) cnt = 0; // 0.5 sec }