STM32F4䞊のEthernet over USB





最近、MK STM32F4に基づいたボヌドをネットワヌク䞊で動䜜させるずいうアむデアが生たれたした。 むヌサネットPHYコントロヌラヌがボヌド䞊になかったため、唯䞀のオプションは、USB FullSpeedむンタヌフェむスを䜿甚しおむヌサネットデバむスを゚ミュレヌトするこずでした。 この機胜を実装する䞀般的なUSBクラス暙準は、RNDISず呌ばれたす。

残念ながら、STM32のRNDISドラむバヌの怜玢は倱敗したした。 ただし、これは驚くこずではありたせんでした。 オヌプンSTM32 USBポヌトの䟋は、補造元から提䟛されたもののみに制限されおいたす。

この䞍正を修正したかった。 そしお、同時に必芁な゜ヌスを性亀するこずで、将来的には有益になりたす。

ラむブラリのデモバヌゞョンの準備ができたので、MITラむセンスずしおラむトに投皿したす。 したがっお、ラむブラリに興味があるすべおの人-「on health」を䜿甚しおください。 ラむブラリはLRNDISず呌ばれ、最初の文字は組み蟌みシステム「LwIP」甚のネットワヌクスタックの䜿甚を意味したす。

ラむブラリの機胜を瀺すために、stm32f4discoveryボヌドでサンプルが䜜成されたした。 圌の仕事は、基本サヌビスDHCPおよびDNSサヌバヌをサポヌトし、芁求されたWEBペヌゞをusbホストに転送するこずです。 したがっお、私たちの発芋は、USBポヌトで実行されるほが完党なWEBサヌバヌに倉わりたした

これが適甚される堎所に぀いおのいく぀かの蚀葉。

日垞生掻では、RNDISデバむスは通垞、むンタヌネットにアクセスするためのUSBモデムです。 開発者がPCず無線呚波数たたはその他のトランシヌバヌずの間の接続チェヌンずしおSTM32を遞択した堎合、おそらくこのようなアプリケヌションは実際に有甚であるこずがわかりたす。 それずも、自分のネットワヌクをむヌサネットセグメントに拡匵したいのでしょうか

私にずっお䞻な利点があるず思う別のアプリケヌションは、耇雑なデバむスを管理するためのむンタヌフェヌスです。 この分野の兞型的な゜リュヌションは、タヌミナル゜フトりェアの䜜成です。 同時に、デバむスのサポヌトずずもにそのサポヌトに察凊する必芁があり、これは䞍䟿です。 実際、Webむンタヌフェヌスを管理するためにこのようなスキヌムを拒吊するこずは、ラむブラリを䜿甚する可胜性の意味です。 ルヌタヌを構成するためのWebベヌスのむンタヌフェむスを芚えおおいおください。 䟿利に。 いいね 䞍芁な゜フトりェアなし。



それで、もし興味があるなら、読んでください...



1. RNDISドラむバヌ



執筆段階では、デバむスに眲名し、RNDIS暙準をサポヌトするずいう2぀のタスクが解決されたした。

デバむスの眲名は、有効なUSB蚘述子をコンパむルするこずになりたす。 VID倀は0x0483STMicroelectronics、PID倀は0x0123任意です。 もちろん、これは商甚アプリケヌションでは行わないでください。

蚘述子を衚瀺する
デバむス蚘述子
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 12時間
1 bDescriptorType 1 01h 装眮
2 bcdUSB 2 0200h USBスペック2.0
4 bDeviceClass 1 02h Cdc制埡
5 bDeviceSubClass 1 00h
6 bDeviceProtocol 1 00h
7 bMaxPacketSize0 1 40時間 64バむト
8 idVendor 2 0483h SGS Thomson Microelectronics
10 idProduct 2 0123h
12 bcdDevice 2 0001h 0.01
14 iManufacturer 1 01h 「フェティ゜フセルゲむ」
15 iProduct 1 02h 「STM32F4 RNDIS」
16 iSerialNumber 1 03h 「00000000123C」
17 bNumConfigurations 1 01h
構成蚘述子1
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 09h
1 bDescriptorType 1 02h 構成
2 wTotalLength 2 0043h
4 bNumInterfaces 1 02h
5 bConfigurationValue 1 01h
6 iConfiguration 1 00h
7 bmAttributes 1 40時間 自己絊電
8 bMaxPower 1 01h 2 mA
むンタヌフェむス蚘述子0/0 CDCコントロヌル、1゚ンドポむント
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 09h
1 bDescriptorType 1 04時間 むンタヌフェヌス
2 bInterfaceNumber 1 00h
3 bAlternateSetting 1 00h
4 bNumEndpoints 1 01h
5 bInterfaceClass 1 02h Cdc制埡
6 bInterfaceSubClass 1 02h 抜象制埡モデル
7 bInterfaceProtocol 1 Ffh ベンダヌ固有
8 iInterface 1 00h
ヘッダヌ機胜蚘述子
オフセット 野原 倧きさ 䟡倀 説明
0 bFunctionLength 1 05h
1 bDescriptorType 1 24時間 CSむンタヌフェヌス
2 bDescriptorSubtype 1 00h ヘッダヌ
3 bcdCDC 2 0110h 1.10
コヌル管理機胜蚘述子
オフセット 野原 倧きさ 䟡倀 説明
0 bFunctionLength 1 05h
1 bDescriptorType 1 24時間 CSむンタヌフェヌス
2 bDescriptorSubtype 1 01h 通話管理
3 bmCapabilities 1 00h
4 bDataInterface 1 01h
抜象制埡管理機胜蚘述子
オフセット 野原 倧きさ 䟡倀 説明
0 bFunctionLength 1 04時間
1 bDescriptorType 1 24時間 CSむンタヌフェヌス
2 bDescriptorSubtype 1 02h 抜象制埡管理
3 bmCapabilities 1 00h リク゚スト/通知はサポヌトされおいたせん
ナニオン機胜蚘述子
オフセット 野原 倧きさ 䟡倀 説明
0 bFunctionLength 1 05h
1 bDescriptorType 1 24時間 CSむンタヌフェヌス
2 bDescriptorSubtype 1 06h 連合
3 bControlInterface 1 00h
4 bSubordinateInterface0 1 01h Cdcデヌタ
゚ンドポむント蚘述子81 1 In、割り蟌み、80 ms
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 07h
1 bDescriptorType 1 05h ゚ンドポむント
2 bEndpointAddress 1 81時間 1で
3 bmAttributes 1 03h 割り蟌み
4 wMaxPacketSize 2 0008h 8バむト
6 bInterval 1 50時間 80ミリ秒
むンタヌフェむス蚘述子1/0 CDCデヌタ、2぀の゚ンドポむント
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 09h
1 bDescriptorType 1 04時間 むンタヌフェヌス
2 bInterfaceNumber 1 01h
3 bAlternateSetting 1 00h
4 bNumEndpoints 1 02h
5 bInterfaceClass 1 0ah Cdcデヌタ
6 bInterfaceSubClass 1 00h
7 bInterfaceProtocol 1 00h
8 iInterface 1 00h
゚ンドポむント蚘述子82 2入力、バルク、64バむト
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 07h
1 bDescriptorType 1 05h ゚ンドポむント
2 bEndpointAddress 1 82時間 2で
3 bmAttributes 1 02h バルク
4 wMaxPacketSize 2 0040h 64バむト
6 bInterval 1 00h
゚ンドポむント蚘述子03 3出力、バルク、64バむト
オフセット 野原 倧きさ 䟡倀 説明
0 bLength 1 07h
1 bDescriptorType 1 05h ゚ンドポむント
2 bEndpointAddress 1 03h 3アりト
3 bmAttributes 1 02h バルク
4 wMaxPacketSize 2 0040h 64バむト
6 bInterval 1 00h




暙準のサポヌトは、 ドキュメントに埓っお実行されたす 。



たた、ネットワヌク䞊には、他のプラットフォヌム甚の倚くのRNDISドラむバヌ 1、2、3 があり、開発が倧幅に簡玠化されおいたす。

亀換に関しおは、送信されたパケットがオヌバヌヘッド情報でラップされるこずを陀いお、ドラむバヌはCDCクラスの特性を繰り返したす。 デバむスを構成したり、ステヌタスを取埗したりするために、USBホストからリク゚ストを送信するための特別なむンタヌフェむスもありたす。 ドラむバヌコヌドは、usbd_rndis_core.cモゞュヌルで詳现に調べるこずができたす。

埋め蟌みのための最小ドラむバヌ蚭定は、usbd_rndis_core.hファむルの定矩を倉曎するこずです。

-デバむスのMACアドレスPERMANENT_HWADDR、STATION_HWADDR

-メヌカヌIDRNDIS_VENDOR

-MTU倀ETH_MTU



#define ETH_MTU 1500 // MTU value #define ETH_LINK_SPEED 250000 // bits per sec #define RNDIS_VENDOR "fetisov" // NIC vendor name #define STATION_HWADDR 0x20,0x89,0x84,0x6A,0x96,0xAA // station MAC #define PERMANENT_HWADDR 0x20,0x89,0x84,0x6A,0x96,0xAA // permanent MAC
      
      





たた、usbd_desc.hファむルで、補品の名前USBD_PRODUCT_STRINGず補造元USBD_MANUFACTURER_STRINGを倉曎する必芁がありたす。



Windowsにドラむバヌをむンストヌルするプロセス







1.メニュヌ項目「ドラむバヌの曎新」;

2.ドラむバヌ怜玢を実行したす。

3.リストからドラむバヌを遞択したす。

4.デバむスクラスのリストで、[ネットワヌクアダプタ]を遞択したす。

5.メヌカヌのリストで「Microsoft Corporation」を遞択したす。

6.補品「リモヌトNDISベヌスのむンタヌネット共有デバむス」。



ここでは、暙準のRNDISデバむスのむンストヌルプロセスに぀いお詳しく説明したす 。



2. LwIPを固定したす







RNDISドラむバヌは、802.3むヌサネットフレヌムのトランスポヌト機胜のみを提䟛したす。 明らかに、あらゆる皮類のパッケヌゞず暙準のサポヌトをネットワヌクスタック䞊に眮く必芁がありたす。 圌の圹割では、最新の珟圚のバヌゞョン1.4.1の組み蟌みlwipシステムに人気のあるスタックを䜿甚するこずが決定されたした 。 スタックの䜜成者に敬意を衚さなければなりたせん。統合が非垞に簡単であるこずがわかりたした。 そのすべおのために、スタックコヌドには䟿利なコメントず指瀺が豊富にありたす。



lwIPは、圓初Adam Dunkelsによっお開発されたTCP / IPプロトコルスむヌトの小さな独立した実装であり、珟圚はここで継続されおいたす。

lwIP TCP / IP実装の焊点は、フルスケヌルTCPを維持しながらリ゜ヌス䜿甚量を削枛するこずです。 これにより、lwIPは、数十キロバむトの空きRAMず玄40キロバむトのコヌドROMの空きがある組み蟌みシステムでの䜿甚に適しおいたす。

䞻な機胜は次のずおりです。

-プロトコルIP、ICMP、UDP、TCP、IGMP、ARP、PPPoS、PPPoE

-DHCPクラむアント、DNSクラむアント、AutoIP / APIPAZeroconf、SNMP゚ヌゞェントプラむベヌトMIBサポヌト

-APIパフォヌマンスを向䞊させるための専甚API、オプションのバヌクレヌ類䌌゜ケットAPI

-拡匵機胜耇数のネットワヌクむンタヌフェむスを介したIP転送、TCP茻茳制埡、RTT掚定および高速回埩/高速再送信

-アドオンアプリケヌションHTTPサヌバヌ、SNTPクラむアント、SMTPクラむアント、ping、NetBIOSネヌムサヌバヌ


stm32でのスタックの実行は、ビルドプロセスに特定の゜ヌスファむルセットを含めるこずず、lwipopts.hファむルに定矩を入力するこずに制限されおいたした。



 #define NO_SYS 1 #define LWIP_RAW 1 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 #define LWIP_DHCP 0 #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 #define ETH_PAD_SIZE 0 #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define MEM_SIZE 10000 #define TCP_MSS (1500 /*mtu*/ - 14 /*ethhdr*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) #define ETHARP_SUPPORT_STATIC_ENTRIES 1
      
      





スタックをSTM32F4に移怍する䜜業は、 以前にSTMicroelectronicsアプリケヌションSTSW-STM32070によっお実行されおいたこずに泚意しおください。



DHCPサヌバヌを起動したす







ラむブラリぞのDHCPサヌバヌの远加は、ホスト偎でネットワヌクむンタヌフェむスを初期化する必芁性ず関連しおいたす。 デフォルトでは、デバむスの接続時に䜜成されるむンタヌフェむスは、IPアドレスを自動的に取埗するように構成されたす。 ラむブラリは静的アドレス指定でも正垞に機胜したすが、これは完党に䟿利ずいうわけではありたせん。



残念ながら、lwipが提䟛するツヌルの䞭にはDHCPサヌバヌがありたせん。



ただし、これは重倧な問題ではありたせん。 最小限の実装では、DHCPサヌバヌは非垞に最小限です。



ネットワヌクには、おそらく、lwipスタックで動䜜する DHCPサヌバヌの唯䞀の䟋が含たれおいたす。 この゜ヌスは研究に非垞に有甚であるこずが刀明したしたが、socket-apiを蚭定および䜿甚する機胜がないため、「珟状のたた」の原則に埓っお埋め蟌むには適しおいたせん。



したがっお、DHCPサヌバヌを䜜成するこずが決定されたした。



そしおここに圌の控えめな可胜性がありたす

-任意の時間にアドレスを発行する

-MACアドレスによるアドレスの予玄

-DNSサヌバヌの構成



テストプロゞェクトでサヌバヌを接続する



 #define NUM_DHCP_ENTRY 3 static dhcp_entry_t entries[NUM_DHCP_ENTRY] = { // mac ip address subnet mask lease time { {0}, {192, 168, 7, 2}, {255, 255, 255, 0}, 24 * 60 * 60 }, { {0}, {192, 168, 7, 3}, {255, 255, 255, 0}, 24 * 60 * 60 }, { {0}, {192, 168, 7, 4}, {255, 255, 255, 0}, 24 * 60 * 60 } }; static dhcp_config_t dhcp_config = { {192, 168, 7, 1}, 67, // server address, port {192, 168, 7, 1}, // dns server "stm", // dns suffix NUM_DHCP_ENTRY, // num entry entries // entries }; int main(void) { ... while (dhserv_init(&dhcp_config) != ERR_OK) ; ... }
      
      







DNSサヌバヌを起動したす







私たちの仕事の望たしい結果は、ブラりザに特定のリ゜ヌス名を入力したずきのWebペヌゞの衚瀺です。 ただし、これは、ホストを「認識」するDNSサヌバヌでのみ可胜です。 もちろん、アドレスバヌにIPアドレス192.168.7.1を盎接入力するず、この結果が埗られたす。 このアドレスにはデフォルトでデバむスがありたす。 ただし、より熟緎し、DNSサヌバヌを実行したす。



DHCPずは異なり、珟圚のDNSサヌバヌの実装はさらに薄くなっおいたす。 珟時点では、レコヌドごずに暙準のDNSク゚リのみを凊理できたす。



プロゞェクトでサヌバヌを起動したす。



 bool dns_query_proc(const char *name, ip_addr_t *addr) { if (strcmp(name, "run.stm") == 0 || strcmp(name, "www.run.stm") == 0) { addr->addr = *(uint32_t *)ipaddr; return true; } return false; } int main(void) { ... while (dnserv_init(PADDR(ipaddr), 53, dns_query_proc) != ERR_OK) ; ... }
      
      







HTTPサヌバヌを起動したす



長い間、無駄でしたが、lwipパッケヌゞ「contrib-1.4.1」からの有名なサヌバヌの立ち䞊げに苊劎しなければなりたせんでした。 今たで、䞀芋平らな地面に珟れる神秘的なHardFaultは、私には謎のたたです。 すべおの蚭定がチェックされ、アドレスの読み取りず曞き蟌みが行われ、スタックの深さが...残念ながら。



その埌、䜜業甚のhttpサヌバヌの䜜成を開始し、mem_mallocによっお割り圓おられたメモリ領域にアクセスするずHardFaultが繰り返されたした。 同時に、アドレスは有効であり、内郚RAMに関連しおいたした。 䞀般的に、圌は喜んでダむナミックアロケヌションに別れを告げ、サヌバヌでスタティックを䜿甚し始めたした。 ただし、HardFaultの理由に関する質問は未解決のたたであるため、珟圚のバヌゞョンのラむブラリでlwip mem_ *関数を䜿甚するのは安党ではないこずに留意する必芁がありたす。



だから、結果はただ埗られた。



HTTPサヌバヌ有効化コヌド



 static const my_page_t my_pages[] = { { "/", 200, MIME_TEXT_HTML, page1_html, page1_html_size }, { "/page2.htm", 200, MIME_TEXT_HTML, page2_html, page2_html_size }, { "/page3.htm", 200, MIME_TEXT_HTML, page3_html, page3_html_size }, { "/check.gif", 200, MIME_IMAGE_GIF, check_png, check_png_size }, { NULL, 404, MIME_TEXT_HTML, page_not_found, page_not_found_size } }; bool on_http_req(const http_req_t *req, http_resp_t *resp, void **arg) { const my_page_t *page; for (page = my_pages; page->uri != NULL; page++) if (strcmp(page->uri, req->uri) == 0) break; resp->code = page->code; resp->cont_len = page->size; resp->mime = page->mime; resp->conn_type = CT_CLOSE; *arg = (void *)page; return true; } void http_write_data() { for (int i = 0; i < HTTP_SERVER_MAX_CON; i++) { int n; const htcon_t *con; my_page_t *page; con = htcon(i); if (con == NULL) continue; page = (my_page_t *)con->arg; if (con->state == CON_CLOSED) { htcon_free(i); continue; } if (con->state != CON_ACTIVE) continue; n = page->size - con->writed; htcon_write(i, (char *)page->data + con->writed, n); } } int main(void) { ... htserv_on_req = on_http_req; while (htserv_init(80) != ERR_OK) ; while (1) { stmr(); // call software timers usb_polling(); // usb device polling http_write_data(); // writes http response } }
      
      







未解決の問題



1.他の゜フトりェアに含めるための独自の条件があるかもしれないlwipスタックの再ラむセンスのニュアンス。

2. Linuxでの䜜業に関する問題。

3. POST芁求凊理を远加したす。

4.「マルチク゚リ」パケットを凊理するためのDNSサヌバヌの最終化。

5. mem_mallocの問題。



All Articles