Mit dieser Library kann man mit dem STM32F4-Discovery-Board und einem extern angeschlossenen PHY (von Texas Instruments “DP83848C”) und einer RJ45-Buchse einen HTTP-Webserver realisieren.
Die Webseite(n) müssen zuvor mit einem PC-Programm in ein C-File gewandelt werden, das dann im Sourcecode eingebunden wird. Eine Anleitung dazu findet sich im Netz.
Es können CGI-Befehle in die Webseite integriert werden um z.B. GPIOs zu schalten oder Messwerte auszulesen. (Im Beispiel können die 4 LEDs vom Board geschaltet werden und der Spannungswert an PA3 wird zyklisch angezeigt)
Diese Funktionen können auch deaktiviert werden, wenn man sie nicht braucht.
Als IP-Stack wird der OpenSource “LwIP” in der Version 1.3.2 benutzt. Und als Schnittstelle zum PHY wird der RMII-Mode benutzt (der MII-Mode funktioniert beim Discovery-Board nicht, weil die benötigten Pins nicht vorhanden sind)
Falls DHCP aktiviert ist, holt sich das Modul die IP-Adresse vom Router, falls nicht kann eine statische IP im H-File eingetragen werden.
BUG HINWEIS : im File “stm32f4x7_eth_bsp.c” wird bei der Initialisierungs-Funktion “ETH_MACDMA_Config” ein Software-Reset ausgelöst und mit einer While-Schleife gewartet bis der Reset fertig ist. Bei meinen Tests hat diese Funktion nicht immer sauber funktioniert (k.A. warum) und blieb in einer Endlosschleife hängen. Ich habe dann als Workaround einen Timeout-Counter hinzugefügt.
(laut suche im Internet ist dieser Fehler bei mir kein Einzelfall)
Abhilfe beim auftreten des Fehlers waren bei mir :
1. nochmal am Board einen Reset per Push-Button auslösen.
2. Die Ethernet-Clock-Enable Zeile NACH dem Reset machen (und nicht davor).
3. Den GPIO PA8 als MCO zu initialisieren (obwohl der gar nicht benutzt wird)
Beispielbilder :
Benutzte Pins :
1 2 3 4 5 6 7 | PA1 = RMII_Ref_Clk PC1 = ETH_MDC PA2 = ETH_MDIO PC4 = RMII_RXD0 PA7 = RMII_CRS_DV PC5 = RMII_RXD1 PB11 = RMII_TX_EN PB12 = RMII_TXD0 PB13 = RMII_TXD1 PB14 = RMII_INT |
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : GPIO, SYSCFG, EXTI, MISC Benutzte Librarys : keine |
Enumerationen :
1 2 3 4 5 | typedef enum { HTTP_SERVER_OK =0, HTTP_SERVER_ETH_MACDMA_ERR, HTTP_SERVER_ETH_PHYINT_ERR }HTTP_SERVER_STATUS_t; |
Funktionen :
1 2 | HTTP_SERVER_STATUS_t UB_HTTP_Server_Init(void); // zum init vom Server void UB_HTTP_Server_Do(void); // muss zyklisch aufgerufen werden |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | //-------------------------------------------------------------- // File : main.c // Datum : 12.05.2013 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.0 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der HTTP-Server Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_http_server.h" #include "stm32_ub_led.h" int main(void) { HTTP_SERVER_STATUS_t check; SystemInit(); // Quarz Einstellungen aktivieren // LEDs initialisieren UB_Led_Init(); // HTTP-Server initialisieren check=UB_HTTP_Server_Init(); if(check==HTTP_SERVER_OK) { // wenn Server ok UB_Led_On(LED_GREEN); } else { // bei einem Fehler UB_Led_On(LED_RED); } while(1) { // HTTP-Server zyklisch aufrufen UB_HTTP_Server_Do(); } } |
Hier die Library zum Download :
Hier der komplette CooCox-Projektordner zum Download :
Erstmal danke für den Code. Ich habe bislang kein anderes Coocox / STM32F4 / Ethernet Beispiel gefunden, das auf Anhieb compilierbar wäre! Meine Testplattform ist ein Olimex STM32F4-E407. Leider hat uns Olimex einen KS8721 auf die F4-Boards gesetzt, so dass es erstmal geheißen hat “such den Unterschied”.
Der größte Unterschied liegt im der RMII-Interrupt Behandlung. Die Register des KS8721 bieten mehr Interrupt Quellen und Flags. Zum Testen habe das Interrupt-Handling erstmal deaktiviert.
Zu meinem krassen Erstaunen läuft der lwip trotzdem, komplett mit CGI.
Nun gilt es eigene Seiten zu basteln und die Software auf Herz und Nieren zu testen.
Nochmal – Danke für die Codebasis!
Kein Problem, hört man gerne wenn etwas gleich funktioniert. Schön wäre es, wenn man die Seiten von SD-Karte laden könnte und nicht erst wandeln und ins Flash packen müsste. Hab aber leider im Moment andere “Baustellen”. Gruss
Ich habe gerade einen Bugfix-Vorschlag zum Thema SSI-Performance beim lwip geposted (langsame Abarbeitung von mehr als einem Tag). Vielleicht hilft jemandem die Info weiter:
https://savannah.nongnu.org/bugs/?31948
Ich bin die Tage auf gewaltigen Widerstand gestoßen, als ich den HTTP-Server auf ein MountaineerETH-Board portieren wollte.
Die Boards sind eigentlich Basis für .NET Gadgeteer: http://www.netmf.com/gadgeteer
http://www.mountaineer-boards.com/home/ethernet-mainboard/
Die Besonderheit ist, dass die Boards das große, pinfressende MII-Interface verwenden, statt des RMII. Die PHY ist ein 78Q2123.
Frage: hat evtl. jemand einen erfolgreichen Port durchführen können?
Ich habe den Webserver am laufen.
Leider sind meine Pings im Bereich von 100 – 400ms.
Ich habe den PB14 = RMII_INT nicht anngeschlossen.
Geht dieser an den Pin7 vom PHY? Liegt es daran?
Ja, PB14 geht an Pin7. Keine Ahnung ob diese fehlende Leitung schuld ist. Hast du einen Router oder Switch dazwischen oder eine direkt Verbindung vom PC zum PHY ?
Hallo Uwe,
großes Kompliment für deine tolle Seite + Library. Sie hat mir schon bei vielen Projekten weiterhelfen können.
Habe mir nun das stmF4Discovery Board + Base Board zugelegt und dein HTTP_Server-Demoprogramm drauf geladen. Allerdings kann ich das Board nicht anpingen… Habe nur die IP Adresse auf 192.168.2.10 und das Gateway auf 192.168.2.1 geändert. Den Rest so gelassen wie er ist.
Hast du mir einen Tipp was ich falsch mache?
Besten Dank,
Fabi
leuchtet die grüne LED zum zeichen das der Server läuft ?. Häng die Platine mal per CrossOver-Ethernet-Kabel direkt an deinen PC (also ohne Switch oder Router) und achte darauf das dein PC auch im Adressraum 192.168.2.x liegt. Versuch dann den Ping nochmal.
Hallo,
1. mein Fehler dass ich diese Demoversion verwendet habe… Das Base Board hat den LAN8720 verbaut.
2. Habe nun das Show4_Projekt aufgespielt mit SD Karte, LED Leuchtet grün, abermals kein PING.
Habe #define F4D in stm32_ub_http_server.h gesetzt. Muss ich sonst noch was beachten?
Vorsicht der Define “F4D” muss in den Compiler Settings gemacht werden (weil er in mehreren Files abgefrag wird) also bei CoIDE unter “Configuration” den Define “F4D” hinzufügen !! und laut einem Bugreport von “Holger” fehlt dann anscheined noch die Systick-Konfig, hab das aber selbst nicht gepüft.
Danke, Problem war mit dem korrekten Define von F4D gelöst!
Mich würde nur der Vollständigkeit halber interessieren, wo das #define F4D vorkommt, ich kann die Zeichenkette “F4D” in der Bibliothek nirgendwo finden.
Kann jemand erklären wofür das gebraucht wird/wurde?
in meiner LIB kommt dieser Define gar nicht vor, der war im Original-Beispiel von ST vorhanden.
Moin Moin,
bei mir funktioniert irgendwie leider nichts. Weder IP noch MAC wird erkannt. Pingen kann ich dementsprechend auch nicht. Hab den PHY direkt über ein Crossover an meinem Laptop. LaptopRechner über das Crossover funktioniert.
PB14 = RMII_INT ist allerdings nicht angeschlossen. Ist bei meinem Phy auch nicht rausgeführt. Ich habe mich an die Verkabelung von http://blog.tkjelectronics.dk/2012/08/ethernet-on-stm32f4discovery-using-external-phy/ gehalten. Die ist bis auf PB14 identisch.
Hab schon diverse Librarys usw. und steh nun auf dem Schlauch.
Die Kabellängen zwischen Board und PHY sind 10cm. Liegt es daran?
Das Board ist das normale STM32F4Discovery und als PHY wird der von Waveshare verwendet. Mit dem DP83848
Viele Grüße
Jo
So,
Probleme konnten behoben werden. Habe die Kabel von 10 cm auf ca 6cm gekürzt und wieder verkabelt. Jetzt läuft er.
Hi,
auf Anhieb kompilierbar, die Grüne LED leuchtet. PB14 = RMII_INT kann ich nicht anschließen weil es den Pin auf meinem DP83848 nicht gibt. Hab dieses Projekt probiert: http://blog.tkjelectronics.dk/2012/08/ethernet-on-stm32f4discovery-using-external-phy/ und es funktioniert. Verstehe nur nicht warum deines nicht geht … Woran könnte es liegen?
Die Verbindungen wären schön kurz ca 5cm!
Grüße
Michi
kannst du das board auf “192.168.0.10″ pingen ?
In meinem Beispiel ist “DHCP” aus !
Geht auch nicht kommt die Meldung: Zeitüberschreitung der Anforderung.
liegt dein PC im gleichen Adressraum ?
Ja beides hängt an meinem router!
der Router vergibt die Adressen normalerweise per DHCP kontrolliere nochmal am PC per “ipconfig” ob dieser wirklich eine Adresse “192.168.0.x” besitzt ich vermute eher was mit “192.168.178.x”
dann kannst du noch zwei sachen probieren
1. den PC direkt an die Platine anschließen und am PC manuell eine IP vergeben
2. Im H-File “DHCP” einschalten
DHCP ein, und läuft! Danke
Gruß
Simon
Hallo,
kann mir jemand sagen ob und wenn für was RMII_INT verwendet wird. Ich mache gerade eine Platine und würde den Pin PB14 gerne für etwas anderes nutzen. Bei anderen Projekten die ich gefunden habe wird dieser Pin nicht verbunden.
Im Datenblatt des DP…. heißt es:
The Power Down and Interrupt functions are multiplexed on pin 7 of the device. By default, this pin functions as a power down input and the interrupt function is disabled. Setting bit 0 (INT_OE) of MICR (0x11h) will configure the pin as an active low interrupt output.
Jetzt konnte ich in den Sourcen zwar finden das PB14 verwendet wird, wird aber auch der Interrupt initialisiert? Falls nein, dann würde mir doch ein Pullup reichen um den Phy Aktiv zu halten?
POWER DOWN: The pin is an active low input in this mode and should be asserted low to put the device in a Power Down mode.
Grüße
Malte
Hallo zusammen,
hat schon mal jemand mit einem anderen Phy dieses Beispiel zum laufen gebracht?
Ich habe hier einen eigenen Aufbau mit dem micrel KSZ8081RNB und komme leider nicht weiter
Gruß joof
Hallo,
in der Funktion tcp_send_empty_ack und tcp_keepalive sind die Zeilen tcphdr = tcp_output_set_header jeweils auskommentiert. In den Originalsourcen sind sie aber drin. Diese Zeilen füllen den TCP header z.B. für leere ACK-Pakete aus. Wenn man die auskommentiert läßt und z.B. den Stack anders benutzen will um große Datenmengen zu empfangen gibt es korrupte ACK – Pakete und die Übertragung geht nicht. Wenn ich das wieder mit reinnehme geht alles, warum sind die also hier auskommentiert?
Matthias
Uhhh…das ist zu lange her, kann ich mich nicht erinnern. Vermutlich mein Fehler bei copy&paste.
Hallo,
ich habe den Webserver mit dem STM32E407 zum laufen gebracht.
Einwandfrei muss ich sagen.
Jetzt möchte ich aber wissen, wie ich mittels diesem Webserver weitere GPIOs ansprechen kann. Ich habe leider noch keine Ahnung, wie/wo die Webserverkommunikation im C-Code stattfindet, könntest du mir da bitte weiter Helfen.
Des Weiteren, könntest du mir die Dateien, die du mittels dem Tool “makefsdata.exe” zur “fsdata.c” gewandelt hast zur Verfügung stellen, vielleicht werde ich daraus schlauer, wie ich weitere Funktionen einfügen und entfernen kann.
Vielen Dank schoneinmal im Voraus
Grüße
Phil
die files sind alle in der library enthalten. Im Unterordner “ub_lib/http_server/doc”
ah, besten Dank. Habe ich wohl übersehen.
Könntest du mir noch sagen, in welcher c-source-file dann die Checkboxen der http für die LED abgefragt werden und in welcher c-source-file diese dann ein-/ausgeschaltet werden.
Würde mir auf die schnelle einiges erleichtern. Vielen Dank
Gruß Phil
Hallo,
ich versuche mit dieser Webserver Demo, weitere “ADC_Handler” zu implementieren, aber es funktioniert einfach nicht.
Dabei passe ich die Datei “httpd_cgi_ssi.c” sowie die “xxxx.shtml” Seite an. Auf was muss ich alles achten, um mehrere Handler hinzubekommen? Mit dem LED Handler funktionieren mehrere soweit ganz gut.
Danke, MFG J
hab ich mich noch nicht mit beschäftigt
Ich habe das gleiche Problem wie Joof,
”
hat schon mal jemand mit einem anderen Phy dieses Beispiel zum laufen gebracht?
Ich habe hier einen eigenen Aufbau mit dem micrel KSZ8081RNB und komme leider nicht weiter ”
Ich bekomme den KSZ8081 ebenfalls nicht zum laufen, habe vorher einen ST802RT1A verwendet, der lief einwandfrei. Muss ich noch was in den Headerfiles ändern? In dem “stm32f4x7_eth_conf.h” finde ich PHY anhängige Register, muss da etwas angepasst werden?
Gruß joof
In dem Header-File finde ich folgende Zeile:
#define PHY_SR ((uint16_t)17) /* Value for ST802RT/STE101P PHY */
Muss ich da was anpassen?
Hallo,
ich habe den Webserver lokal zum laufen bekommen. Also ich kann innerhalb meines eigenen Netzwerkes mittels fester IP-Adresse auf das Board zugreifen und eine Weboberfläche aufrufen/steuern.
Jetzt möchte ich aber nicht lokal darauf zugreifen können, sondern mittels Internet.
– Ist das mit diesem Webserver möglich?
– Auf was muss ich achten/anpassen, dass dies funktioniert?
– Gibt es Examples hierfür?
Viele Grüße und Danke für die Mühen.
Jens
das muss am Router eingestellt werden. Thema : Portweiterleitung
wenn ich versuche DHCP zu aktivieren, bekomme ich keine Verbindung mit dem Port.
Was muss ich da alles aktivieren (wie z.B. #define USE_DHCP)??
Wie kann ich danach auf den Server zugreifen? IP (die ich dann nicht kenne)? oder wie funktioniert dies dann?
Danke
statt “port” meinte ich natürlcih “Board”
schau am router nach, der vergibt die ip nummern,
oder geb sie per UART oder LCD aus.
Hey,
Server funktioniert ohne problem, wenn beim Starten des Boards das Netzwerkkabel angeschlossen ist.
ABER,wenn ich das Board starte und es dabei nicht am Netzwerk angeschlossen ist, dann funktioniert der Server ja nicht. Jetzt habe ich eine Schleife eingebaut, bei dem nach dem Starten des Boards (Ethernetkabel beim Start noch nicht angeschlossen), solange in der Schleife (while) geblieben wird, bis ein bestimmter Button gedrückt ist, um nochmals die Funktion
// HTTP-Server initialisieren
check=UB_HTTP_Server_Init();
aufzurufen. Wenn bei diesem erneuten Aufruf dann das Ethernet-Kabel angeschlossen ist, dann wird die while-Schleife erfolgreich verlassen, da
check==HTTP_SERVER_OK;
ist.
Aber anschließend funktioniert der Server trotzdem nicht. Es wird zwar dies zyklisch aufgerufen:
//HTTP-Server zyklisch aufrufen
UB_HTTP_Server_Do();
aber nach ein paar mal schon nichtmehr. (bleibt irgendwo hängen oder so,… aber genau weis ich es auch nicht).
Was muss ich bei dieser Aktion alles beachten? Irgendwelche Funktionen, GPIOs, etc…. zurücksetzen/deinitialisieren??
Vielen Dank.
Gruß Flou