Forum: Mikrocontroller und Digitale Elektronik einfache und performante W5500 LIB


von Marco H. (damarco)


Lesenswert?

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 ;) .

von Arduinoquäler (Gast)


Lesenswert?

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 .....

von spess53 (Gast)


Lesenswert?

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

von Arduinoquäler (Gast)


Lesenswert?

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 ...

von Arduinoquäler (Gast)


Lesenswert?

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.

von Arduinoquäler (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Das wollte ich dir vor Augen halten.

.... nicht dir sondern Marco H.

von Marco H. (damarco)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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...

von spess53 (Gast)


Lesenswert?

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

von Arduinoquäler (Gast)


Lesenswert?

spess53 schrieb:
> Auch hast du das auch schon gemerkt?

Der Thread-Ersteller offensichtlich nicht .....

von Marco H. (damarco)


Lesenswert?

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
von Marco H. (damarco)


Lesenswert?

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
von Karl M. (Gast)


Lesenswert?

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

von Marco H. (damarco)


Lesenswert?

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
von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

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...

von Marco H. (damarco)


Lesenswert?

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
von Marco H. (damarco)


Lesenswert?

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.

von Marco H. (damarco)


Lesenswert?

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
von Marco H. (damarco)


Lesenswert?

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
von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

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.

von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

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
von spess53 (Gast)


Lesenswert?

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

von Marco H. (damarco)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

Wow, echt cool,

magst du den Code teilen?

Sieht echt stark aus

von Marco H. (damarco)


Lesenswert?

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 ...

von Teilhaber (Gast)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

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

von Markus (Gast)


Lesenswert?

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.

von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

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
von Arduinoquäler (Gast)


Lesenswert?

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 <---

von Marco H. (damarco)


Lesenswert?

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
von Marco H. (damarco)


Lesenswert?

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
Noch kein Account? Hier anmelden.