Die ioLib des Herstellers ist der reine Horror. Hat jemand einen Tip für eine einfache LIB in C ? Die Arduino LIBs gehören nicht dazu ;) .
Marco H. schrieb: > Die ioLib des Herstellers ist der reine Horror. Du müsstest mal selbst einen TCP/IP Stack schreiben dann würdest du anders reden und dankbar sein. Einfach geht nicht, dafür ist das Zeug zu gut .....
Hi >Du müsstest mal selbst einen TCP/IP Stack schreiben dann >würdest du anders reden und dankbar sein. Wozu braucht man dafür einen TCP/IP-Stack? >Einfach geht nicht, dafür ist das Zeug zu gut ..... Du hast das schon mal gemacht? MfG spess
spess53 schrieb: > Du hast das schon mal gemacht? Mit "einfach" bezog ich mich auf die Anforderung des Thread-Erstellers. Den W5100 betreibe ich bereits (ohne Arduino Lib) erfolgreich ...
spess53 schrieb: > Wozu braucht man dafür einen TCP/IP-Stack? Braucht man nicht, genau das erspart dir der Chip. Das wollte ich dir vor Augen halten. Den Rest an nicht "einfacher LIB" musst du selbst Leisten.
Der wz5500 stellt 8 sockets zur Verfügung und nimmt einen bis zum IP Layer alles ab. Den Stack muss ich nicht schreiben das macht der W5500 :) Was man dann machen muss ist die Mechanismen für die IP Dienste zu programmieren. Ich glaube Ping, ARP etc. stellt der W5500 schon zur Verfügung. Im Prinzip bekommt man das mit der iolib schon zum laufen. Aber diese ist nicht wirklich schön programmiert was die Art und weise angeht. Durch die vielen Funktionspionter schwer zu durchblicken was wo aufgerufen wird. Man muss ja das Rad nicht jedes mal neu erfinden, deshalb meine Frage. Keine Ahnung warum man hier immer zu Usern von der Leiter nach unten sprechen muss und dabei wenig hilfreiche Antworten gibt.
Marco H. schrieb: > Im Prinzip bekommt man das mit der iolib schon zum laufen. Aber diese > ist nicht wirklich schön programmiert was die Art und weise angeht. > Durch die vielen Funktionspionter schwer zu durchblicken was wo > aufgerufen wird. Das ist aber bei jedem ereignisorientierten Design immer das gleiche "Drama". Man muss dazu einfach nur das Konzept der ereignisauslösenden Komponente verstehen. Ja, das ist schwerer, als simple Kontrollstrukturen in einem linearen Codeblock zu durchschauen. Aber JEDER Programmierer muss mit sowas klarkommen. Sonst ist er einfach keiner. Klar?! > Man muss ja das Rad nicht jedes mal neu erfinden Wie ich diesen Lieblingsspruch der Dummen und Faulen hasse...
Hi >Den W5100 betreibe ich bereits (ohne Arduino Lib) erfolgreich ... Ich den W5100 seit 2011 und den W5200 sei 2012 unter Assembler. >Braucht man nicht, genau das erspart dir der Chip. Das >wollte ich dir vor Augen halten. Den Rest an nicht >"einfacher LIB" musst du selbst Leisten. Auch hast du das auch schon gemerkt? MfG Spess
spess53 schrieb: > Auch hast du das auch schon gemerkt? Der Thread-Ersteller offensichtlich nicht .....
Ich habe die iolib schon verstanden und vorher auch die Referenz studiert. So Ereignis orientiert ist die ioLib nicht und auch kein Hexenwerk. Nur eben unschön Programmiert und wenn man dies ändern wollte müsste man das ganze auf den Kopf stellen. Es gibt Leute die ihren Code gerne zur Verfügung stellen und welche die ihn lieber verstecken. Meist haben sie auch gründe dafür das keiner rein schaut damit man erkennt das sie nur halb so viel auf den Kasten haben ;) Mir soll es egal sein, ich bekomme das schon zum laufen.
:
Bearbeitet durch User
Siehe da es funktioniert sogar mit der ioLib ;) Allerdings sollte man sich die Mühe machen den zahllosen Wahrungen nachzugehen. Sonst sind unerwünschte Effekte kaum vermeidbar. Nach dem die Ursachen beseitigt wurden, funktioniert der Code sogar.
1 | void DHCP_init(uint8_t s, uint8_t * buf) |
2 | |
3 | pDHCPMSG = (RIP_MSG*)buf; |
Hier wird der Pointer des Datenbuffer übergeben und intern wird die Adresse per cast an pDHCPMSG(RIP_MSG Struktur für die Verbreitung der DHCP Messages) übergeben. Der Programmierer dachte sich er könnte den RX/TX Speicher hierzu benutzen. Nur enthält die Struktur auch uint16 Typen wenn man dies per cast in ein uint8_t Array versucht rein zudrücken mag das ewt. funktionieren erzeugt aber eine berechtigte Warnung"warning increases required alignment of target type [-Wcast-aligary]".
1 | int8_t parseDHCPMSG(void) |
2 | uint8_t ret; |
3 | |
4 | if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0){ret=0;} |
5 | |
6 | return ret; |
Wenn die If bedingt nicht erfühlt ist wird "ret" initialisiert zurückgeben.
1 | uint8_t ret=0; |
löst das Problem ;) Das meinte ich mit Horror und unschön programmiert.
:
Bearbeitet durch User
Hallo, es gibt ja Menschen, die mit den w5500 richtig umgehen können. "Hu tab", ich liebe die Bilder aus dem Blog. http://www.ehajo.de/ethernet-shield-wiznet-w5500.html http://shop.wiznet.eu/w5500-adapter.html https://github.com/ehajo/wiznet http://blog.ehajo.de/ -> w5500
Danke für den Link, so etwas wäre weiter oben hilfreich gewesen. Die meisten Fehler wurden durch den DHCP Code generiert. In ehajo seinen Projekt ist dieser nicht enthalten. Ich vermute da dieser sowie so nicht gebraucht wird. Ich habe Antwortzeiten von 180ms per loopback. Wenn man PC -> Switch -> W5500 und wieder zurück betrachtet kann man damit schon leben. Erstmal das SPI per DMA auslagern und dann schauen wir weiter. Wiznet stellt auch Code für HTTP zur Verfügung. Wenn man es genau betrachtet bringt dieser für einen ARM nicht wirklich einen Vorteil. Außer das er den Socket zur Verfügung stellt. Da viele ARMs die Möglichkeit haben PHYs direkt anzuschließen und die Hersteller auch Ethernet Module mitbringen lohnt sich dies nicht wirklich.
:
Bearbeitet durch User
Karl M. schrieb: > Hallo, > > es gibt ja Menschen, die mit den w5500 richtig umgehen können. > "Hu tab", ich liebe die Bilder aus dem Blog. Hallo Karl, vielen Dank, dass du mich hier verlinkst. Die Lib von Wiznet hatte anfangs noch sehr sehr böse Fehler drin. Wie das aktuell aussieht, weiß ich nicht genau. Wir haben hier bei uns Fehler gefunden, wo irgendwelche Pointer von ner 32-bit Struktur ausgegangen sind, was ja AVRs nunmal nicht sind. Die Bugreports sind zu Wiznet geflossen, ich denke, sowas sollte schon drin sein. DHCP und co läuft hier alles auf den Demoboards bei uns. Ja, wir "können schon so einigermaßen richtig" damit umgehen, das stimmt. Wir machen auch einiges für WIZnet hier in .de, sieht man ja am Blog, sonst wären wir nicht mit auf dem Messestand gewesen. Marco H. schrieb: > Wenn man es genau betrachtet bringt dieser für einen ARM nicht > wirklich einen Vorteil. Außer das er den Socket zur Verfügung > stellt. Da viele ARMs die Möglichkeit haben PHYs direkt > anzuschließen und die Hersteller auch Ethernet Module mitbringen > lohnt sich dies nicht wirklich. Vorteile gibt es da schon, du hast bei WIZnet einen Hardware-TCP-IP-Stack, das bedeutet, dass die gesamte Prozessor und RAM-Last auf dem W5500 liegt. Und dann kommen noch so Kleinigkeiten dazu wie: Wenn jemand ne Attacke im Netzwerk fährt (Controller mit Pings zukleistern zB) das deinen Prozessor nicht zum Erliegen bringt...
Zum Glück ist die Referenz besser als der Code :) Wie gesagt es ist kein Hexenwerk den IC zu verstehen. Ich muss dich enttäuschen der Code ist immer noch so grausam. Das Beispiel mit dem Buffer ist immer noch so drin :( Das mit dem nicht initialisierten return ist gefixt. Das wird auch seine gründe haben. Es ist eben überall so, am verkauf verdient man mehr als am Treiber. Tja und Anbieter so wie du sind dann halt gezwungen für ihre Kunden die Treiber lauffähig anzupassen.
:
Bearbeitet durch User
Habt ihr den HTTP Code auch zum laufen gebracht ? Also bei mir läuft er schon aber wenn ich den mir so anschaue beugen sich die Nackenhaare auf. Es wird mit Strings operiert dessen Speicherbereiche nicht geschützt sind. Um die URL zu entschlüsseln wird ein uint8 Pointer angelegt und dann geht es los . Immer rein ab der Adresse ohne malloc, realloc und free scheinen nicht sehr beliebt zu sein :( Man sollte sich beim HTTP schon Gedanken über das Speichermanagement machen.
und wie böse das endet, hier ein Beispiel.
1 | case METHOD_GET : |
2 | uri_name = get_http_uri_name(p_http_request->URI); |
3 | if (!strcmp((char *)uri_name, "/")) strcpy((char *)uri_name, INITIAL_WEBPAGE); // If URI is "/", respond by index.html |
4 | if (!strcmp((char *)uri_name, "m")) strcpy((char *)uri_name, M_INITIAL_WEBPAGE); |
5 | if (!strcmp((char *)uri_name, "mobile")) strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE); |
6 | find_http_uri_type(&p_http_request->TYPE, uri_name); // Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included) |
Zuerst wird die request Methode ermittelt. Dann muss der String analysiert werden welche Datei angefordert wird und welchen Type diese hat. Alles soweit ok. Nach dem Fund "/ " wird der String durch INITIAL_WEBPAGE = index.html ersetzt. Bis folgendes passiert..
1 | #ifdef _HTTPSERVER_DEBUG_
|
2 | printf("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n",s); |
3 | printf("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE); |
4 | printf("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name); |
5 | #endif
|
Im Debug Mode werden die Informationen auf die Uart ausgegeben zwar per Semihost. Heißt die stdio.h Funktionen werden umgeleitet. Hierzu landen die Daten aus der stdio in einen Buffer und werden dann auf die Uart geschrieben. Nach dem Aufruf von printf() steht nur noch Müll im uri_name. Worauf jeder Aufruf der Daten scheitert. Sobald man DEBUG aktiviert fährt der Code gegen die Wand.
:
Bearbeitet durch User
So ich bin nun etwas weiter. Diverse Bruchstellen wurde beseitigt und es klappt schon ganz gut. Die Ursache aus dem vorherigen Beitrag ist ein Musterbeispiel des Speichermanagement. Die Funktion
1 | get_http_uri_name(p_http_request->URI); |
ermittelt die uri und gibt einen Pointer aus einen Stringarray zurück das in dieser Funktion deklariert wird. Wird die Funktion beendet ist der zurückgegebene Pointer so eine Sache. Denn der Speicherbereich in der Heap für das Array ist nicht geschützt. Es besteht eben dann die Gefahr das beim Aufruf der nächsten Funktion der Inhalt überschrieben wird. Was beim Chinesen funktioniert hatte klappt beim sam3x nicht mehr die printf Funktion überschreibt diesen Bereich. Sehr schnell ist die Sache nicht. Die Datenrate liegt so bei 150kbit/s. Unglücklicherweise hängt die SD-Karte und der W5500 auf dem selben SPI Port.Die Hardware Möglichkeiten die der sam3x bietet bleiben so ungenutzt mit dem shield. Das Problem ist aber er weniger das lesen oder senden von Daten sondern wann der Code abgearbeitet wird. Bei umfangreichen Anwendercode dürfte die Datenrate weiter sinken. 5 Gleichzeitige Clients mit 6 offenen sockets kann man damit schon versorgen. Bei zu vielen werden die Sockets nicht rechtzeitig bearbeitet und Verbindungen abgewiesen.
:
Bearbeitet durch User
So es ist fast geschafft :) alles funktioniert .. - Konfiguration lesen/schreiben Ip/Serial etc. inkl Reset - DHCP - GPIO Label Konfiguration In/Out etc. - GPIO schalten - ADC auslesen und anzeigen - Serial Data auf Usart empfangen und Senden. Nun kann man die Sache optimieren und gff. an andere Architekturen anpassen.
Das Projekt läuft momentan auf einen Arduino Due mit Ethernet Shield 2 und hier ergeben sich gleich folgende Problematiken. - SD Karte und W5500 auf den selben SPI Port - SD Karte kein Card detect etc. - SD Karte nur im SPI Mode obwohl der Sam3x ein Controller dafür hätte - w5500 keine Hardware Interrupts es muss immer der Status der Sockets abgefragt werden und dieser steuert dann die state Maschine. noch offen: DMA Support w5500 zumindest die Status Telegramme bei DMA zusammen zu ketten. Für Daten relativ problematisch oder wenig Sinnvoll da der Buffer vom W5500 pro Socket nur 2k groß ist. Das lesen von der SD-Karte ist der eigentlich Flaschenhals und mehr Blöcke zu lesen wird vermutlich nicht viel bringen. Zumal es keinen Hardware Interrupt gibt und man prüfen muss ob der Buffer vom W5500 schon frei ist. Es könnte ja sein das durch TCP/IP ein Paket erneut angefordert wird und der Buffer wird erst frei wenn der Empfänger das Paket als korrekt empfangen meldet. GPIO Status nicht in den Flash speichern. Momentan wird der Status der GPIO Outs mit in den Flash gespeichert. Also jedes On/Off wird auch im Flash abgelegt. Das hängt mit der Struktur zusammen die dort verwendet wird. Muss noch geändert werden inkl. etwas Code. Des Erfolges wegen erstmals so belassen. Beim GPIO Init wird also der Status wird ausgelesen und die Ports gesetzt. Das finde ich etwas problematisch wenn die 2kW Heizung einfach so nach dem Reboot wieder angeht ;) Außerdem für den Flash nicht so toll und verlangsamt durch wait Perioden die Abarbeitung. Ein paar Warnungen beheben.. Noch ein paar Kleinigkeiten wo der Code umgebaut werden muss sind noch zu beheben. inkl. ein Problem mit dem Json String vom widget.cgi der Linux Firefox meint es wäre nicht Wohl geformt. Ursache sind offenbar \t im sprint. Es funktionierte komischer weise aber schon mal.. Im ganzen trotzdem ein schönes Projekt wo man mit vielen Dingen wie Javascript, Ajax etc. Erfahrungen sammelt.
:
Bearbeitet durch User
Hi >Für Daten relativ problematisch oder wenig Sinnvoll da der >Buffer vom W5500 pro Socket nur 2k groß ist. Stimmt nicht ganz. Du kannst für jeden Socket einen TX- und einen RX-Buffer zwischen 0 und 16k festlegen. Die Grenze von 16k pro Summe der TX-/RX-Buffer bleibt natürlich bestehen. MfG Spess
Dann schrumpft aber auch die Anzahl der Sockets. Bei 16k steht nur ein Socket zur Verfügung. Was bei HTTP etwas unglücklich wäre.
Wow, echt cool, magst du den Code teilen? Sieht echt stark aus
Das eigentliche Projekt kommt aber von Wiznet und war für einen ST µP. Die ganzen Userhandler Funktionen und etlichen Verbesserungen kamen von mir hinzu. Zu Prüfen wäre unter welcher Lizenz der dort enthaltene Code steht. So als Beispiel taugt das Projekt schon. Dieser ist aber sehr umfangreich und nicht immer Verständnisvoll Kommentiert, einige Stellen sogar Chinesisch ;) . Ansonsten steht einer Veröffentlichung nichts im Wege. Bei ehrlichen Interesse die zur Mithilfe führt gerne ...
Markus schrieb: > magst du den Code teilen? Das hilft ja nichts. Der geteilte Code läuft ja nicht da er unvollständig ist. Je mehr Teilhaber desto unvollständiger.
Wenn das hier zu gehört, http://wizwiki.net/wiki/doku.php?id=products:wiz550web:wiz550web_download scheint das frei nutzbar zu sein liegt alles bei Git
Marco H. schrieb: > Ansonsten steht einer Veröffentlichung nichts im Wege. > Bei ehrlichen Interesse die zur Mithilfe führt gerne ... Auf jedenfall habe ich Interesse leider aber keine Netzwerkkarte mit dem W5500 zur Hand würde schaun wie das mit der W5100 läuft.
Ich hätte noch ein Tip um andere vor einer Riesenbauchlandung zu bewahren. Es geht um das lesen des Empfangsregister des W5500. Es gibt zwei Möglichkeiten festzustellen ob neue Pakete angekommen sind. A: per ISR B: lesen des Registers RX_RSR um die Differenz zwischen read u. write pointer sich ausgeben zu lassen. Beim lesen muss man aber eins beachten! Das mitunter wenn man nicht schnell genug ließt können weitere Pakete in den Buffer landen. Beim auslesen ließt man alles aus, man muss selber schauen wie man die Pakete anhand des Protokolls auseinander würfelt. Im TCP Mode quittiert der W5500 die Pakete sofort mit ACK. Das ist vielen offenbar noch nicht aufgefallen, wenn man schneller ließt wie Daten Empfangen werden tritt der Umstand nicht auf. Bei hoher Last oder zu langsamen auslesen fallen Pakete unter den Tisch. Bei MQTT viel mir das auf und ich ging auf die suche nach der Ursache. Die Publish messages hat eine größe von 34 byte, das PubACK 4 =38; das ACK wurde ausgewertet die Publish viel unter den Tisch. Das Problem wurde mit der Überarbeitung der Empfangsroutine behoben.
:
Bearbeitet durch User
Marco H. schrieb: > A: per ISR ISR ist die Abkürzung für Interrupt Service Routine. Ein Solche Routine kann ich beim W5500 erst mal nicht finden. Und wenn sie irgendwo da wäre würde sie nichts tun. Marco H. schrieb: > B: lesen des Registers RX_RSR um die Differenz zwischen read u. write > pointer sich ausgeben zu lassen. Das ist ein unkluge (um nicht zu sagen dumme) Methode, quasi von hinten durch die Brust ins Auge. Ungefähr so wie auf einem 8-Bit Controller einen 16-Bit Register-Wert nicht-atomar schreiben oder lesen. Ich würde ganz einfach das Socket Interrupt Register auswerten. Aber gut, warum einfach wenn's kompliziert auch geht. Marco H. schrieb: > Bei MQTT viel mir das auf ---> fiel <---
Das bringt nicht viel da du zum lesen ja wissen musst wie groß die Daten sind im Buffer. Das RX_RSR musst du sowie lesen und auch das Register für den Buffer Pointer. Doch der W5500 hat einen ISR Pin man muss das Register Sn_IR nicht unbedingt dauert abfragen. Es ergibt sich aber genau das gleiche Problem. Das beim lesen neue Pakete eintreffen. Zwischen Abfrage des RX_RSR und des lesen vergeht eine Zeit x. Nach dem lesen musst du den rx Pointer im W5500 Buffer neu setzen und dem W5500 das durch des sn_CR auch mitteilen. Sonst ließt du immer nur die älteren Pakete aus, die neuen fallen unter den Tisch. Wenn wenig Trafic ist fällt das nicht auf. Das Register RX_RSR gibt die Differenz zwischen Read u. write Pointer aus. Treffen neue Pakete ein wird der write Pointer entsprechend der Länge verschoben. Wird hier null zurückgegeben gibt es nichts zum lesen. So weit ich mich erinnere gibt die Arduino Lib auch nur die Länge vom RX_RSR zurück. Für den Rest musst du dann selber sorgen und wenn man den Umstand nicht bedenkt fallen Pakete unter den Tisch.
:
Bearbeitet durch User
Ein weiteres Kuriosum, das Register Sn_SR gibt 0x10 zurück. Im Datenblatt 1.0.6 gibt es diesen nicht aber Sn_CR dort bedeutet dieser Close. Was dem zustand auch Nahe kommt. Nach dem Reset ist das Register Sn_SR 0 -> Close macht der Server die Verbindung zu zeigt das Register Sn_SR den Inhalt 0x10 . Ich interpretiere das jetzt als Close womit bei mir der gewünschte Effekt eintritt. Nein ich habe die Register nicht verwechselt, die Adressen habe ich Kontrolliert. Zumal der weitere Code dann nicht funktionieren würde. Was noch nicht funktioniert ist der TCP Timeout, nach den Registern müsste dieser nach ca. 32sec auftreten. Sn_IMR wurde gesetzt und auch nochmals gelesen. Die ISR tritt nicht auf. ARP sollte bei 1,8s und TCP bei 31.8sec auftreten. Hmm nochmal nach forschen ;)
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.