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
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.
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
voidDHCP_init(uint8_ts,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_tparseDHCPMSG(void)
2
uint8_tret;
3
4
if((len=getSn_RX_RSR(DHCP_SOCKET))>0){ret=0;}
5
6
returnret;
Wenn die If bedingt nicht erfühlt ist wird "ret" initialisiert
zurückgeben.
1
uint8_tret=0;
löst das Problem ;)
Das meinte ich mit Horror und unschön programmiert.
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.
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.
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.
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..
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.
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.
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.
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
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.
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.
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.
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 ;)