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任意です。 もちろん、これは商甚アプリケヌションでは行わないでください。
蚘述子を衚瀺する
デバむス蚘述子
オフセット野原倧きさ䟡倀説明
0bLength112時間
1bDescriptorType101h装眮
2bcdUSB20200hUSBスペック2.0
4bDeviceClass102hCdc制埡
5bDeviceSubClass100h
6bDeviceProtocol100h
7bMaxPacketSize0140時間64バむト
8idVendor20483hSGS Thomson Microelectronics
10idProduct20123h
12bcdDevice20001h0.01
14iManufacturer101h「フェティ゜フセルゲむ」
15iProduct102h「STM32F4 RNDIS」
16iSerialNumber103h「00000000123C」
17bNumConfigurations101h
構成蚘述子1
オフセット野原倧きさ䟡倀説明
0bLength109h
1bDescriptorType102h構成
2wTotalLength20043h
4bNumInterfaces102h
5bConfigurationValue101h
6iConfiguration100h
7bmAttributes140時間自己絊電
8bMaxPower101h2 mA
むンタヌフェむス蚘述子0/0 CDCコントロヌル、1゚ンドポむント
オフセット野原倧きさ䟡倀説明
0bLength109h
1bDescriptorType104時間むンタヌフェヌス
2bInterfaceNumber100h
3bAlternateSetting100h
4bNumEndpoints101h
5bInterfaceClass102hCdc制埡
6bInterfaceSubClass102h抜象制埡モデル
7bInterfaceProtocol1Ffhベンダヌ固有
8iInterface100h
ヘッダヌ機胜蚘述子
オフセット野原倧きさ䟡倀説明
0bFunctionLength105h
1bDescriptorType124時間CSむンタヌフェヌス
2bDescriptorSubtype100hヘッダヌ
3bcdCDC20110h1.10
コヌル管理機胜蚘述子
オフセット野原倧きさ䟡倀説明
0bFunctionLength105h
1bDescriptorType124時間CSむンタヌフェヌス
2bDescriptorSubtype101h通話管理
3bmCapabilities100h
4bDataInterface101h
抜象制埡管理機胜蚘述子
オフセット野原倧きさ䟡倀説明
0bFunctionLength104時間
1bDescriptorType124時間CSむンタヌフェヌス
2bDescriptorSubtype102h抜象制埡管理
3bmCapabilities100hリク゚スト/通知はサポヌトされおいたせん
ナニオン機胜蚘述子
オフセット野原倧きさ䟡倀説明
0bFunctionLength105h
1bDescriptorType124時間CSむンタヌフェヌス
2bDescriptorSubtype106h連合
3bControlInterface100h
4bSubordinateInterface0101hCdcデヌタ
゚ンドポむント蚘述子81 1 In、割り蟌み、80 ms
オフセット野原倧きさ䟡倀説明
0bLength107h
1bDescriptorType105h゚ンドポむント
2bEndpointAddress181時間1で
3bmAttributes103h割り蟌み
4wMaxPacketSize20008h8バむト
6bInterval150時間80ミリ秒
むンタヌフェむス蚘述子1/0 CDCデヌタ、2぀の゚ンドポむント
オフセット野原倧きさ䟡倀説明
0bLength109h
1bDescriptorType104時間むンタヌフェヌス
2bInterfaceNumber101h
3bAlternateSetting100h
4bNumEndpoints102h
5bInterfaceClass10ahCdcデヌタ
6bInterfaceSubClass100h
7bInterfaceProtocol100h
8iInterface100h
゚ンドポむント蚘述子82 2入力、バルク、64バむト
オフセット野原倧きさ䟡倀説明
0bLength107h
1bDescriptorType105h゚ンドポむント
2bEndpointAddress182時間2で
3bmAttributes102hバルク
4wMaxPacketSize20040h64バむト
6bInterval100h
゚ンドポむント蚘述子03 3出力、バルク、64バむト
オフセット野原倧きさ䟡倀説明
0bLength107h
1bDescriptorType105h゚ンドポむント
2bEndpointAddress103h3アりト
3bmAttributes102hバルク
4wMaxPacketSize20040h64バむト
6bInterval100h


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

たた、ネットワヌク䞊には、他のプラットフォヌム甚の倚くの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の問題。

Source: https://habr.com/ru/post/J248097/


All Articles