mikrocontroller.net

Forum: Compiler & IDEs uIP überrannt?


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe einen ENC28J60 an einem LPC2129 hängen, programmiert mit 
WinARM+uIP (Statemachine, ohne die uIP-Tasks).
Bei bestehender TCP-Verbindung besteht eine Transaktion aus Befehl 
(PC->LPC) und Antwort (LPC->PC). Die Pakete umfassen jeweils wenige Byte 
(<10).
Das ganze funktioniert wunderbar, wenn ich zwischen den Transaktionen 
kurze Pausen mache. Wenn ich die Transaktionen aber in einer 
Endlos-Schleife direkt nacheinander ausführe, dann bleibt nach einigen 
Sekunden die TCP-Verbindung hängen, d.h. der LPC sendet nichts mehr und 
nimmt auch keine neue Verbindung an diesem Port mehr an. Pingen geht 
weiterhin, Interrupts auch...
Man könnte also annehmen, daß ich den uIP-Server zumindest auf diesem 
Port überrenne. Aber warum?
Theoretisch ist das Frage-Antwort-Spiel doch eine eigene 
Synchronisation, ansonsten hat noch TCP sein ACK.

Da das Problem sowohl unter WinXP mit LabView als auch unter Win98SE 
unter Delphi auftritt, vermute ich mal, es liegt nicht direkt am PC.

Ist das Problem auch schon mal bei Euch aufgetaucht? Woran könnte es 
liegen -> wie kann ich es umgehen, ohne mein PC-Programm durch Streuung 
von sleep() auszubremsen? Bin für jede Inspiration dankbar.  :(

Grüße
Andy

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>(Statemachine, ohne die uIP-Tasks).

Du weißt aber schon daß du nur senden darfst, wenn uIP deine 
"Applikation" aufruft?

D.h. du darfst auch nur pro Aufruf max. nur einmal senden!

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, das weiß ich. Liegt daran, daß uip_send() eigentlich die Daten nur 
in den Puffer von uip kopiert (nicht anhängt).

Ich sende bei uip_receive(), behalte davon eine Kopie für 
uip_retransmit() und lösche die dann bei acknowledge.
(Sorry, wenn die Zustände etwas anders heißen, bin gerade am falschen 
Rechner...)

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D.h. du sendest ein Paket, wartest auf das entspr. ACK und sendest dann 
erst das nächste? Das sollte eigentlich funktionieren.

Ansonsten wirf doch mal einen Netzwerksniffer auf deinem PC an.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Prinzip schon.
Fürchte, ich komme doch nicht um Wireshark herum... :(

Wobei mir immer noch nicht so ganz klar ist, wie das überhaupt sein 
kann. Eigentlich werden nie 2 Pakete direkt nacheinander verschickt, 
sondern es geht immer hin & her wie beim Tennis.
Irgendwas übersehe ich noch.

Danke!

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, bin mittlerweile etwas weiter - zumindest mit 2 Erkenntnissen:

1.) Pakete mit Nutz-Datenlängen > 15Byte (PC->LPC) erzeugen ein 
"malformed packet", was angeblich die Mitte eines Framentes ist. Jetzt 
fragt mich bloß nicht, wo Anfang und Ende hin sind...???
Gut, das habe ich PC-seitig in SW behoben.

2.) Das Abstürzen ist ein Konzept-Problem mit dem ACK.
Bisher sah mein Code so aus: Ein TxPuffer, an den die Antworten immer 
angehängt wurden. Beim Retransmit wurde der gesamte Puffer wiederholt, 
bei ACK wurde die Pufferlänge wieder auf 0 gesetzt. Theoretisch logisch!
Praxis: Wenn ich die Daten zu schnell nacheinander sende, dann gibt es 
vom PC kein explizites ACK mehr, sondern eine Kombination aus PUSH & 
ACK. Bei dieser Kombi ruft uIP anscheinend die ACK-Routine nicht auf, so 
daß der Sendepuffer immer weiter angehängt wird -> irgendwann voll.
Da ich im switch() der Statemachine ACK vor Empfang prüfe, gehe ich 
davon aus, daß uIP ein Problem mit dieser Kombi hat.

Ich tüftle mal weiter, die Retransmit-Option will ich unbedingt möglich 
lassen, auch wenn das Ganze nur im lokalen Netz läuft (und es daher 
wahrscheinlich nicht zu oft auftritt). Wer Ideen oder gar Lösungen hat, 
sei mir willkommen.  ;)

Gruß Andy

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie groß ist denn dein uIP-Sende/Empfangspuffer?

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Volker,
UIP_CONF_BUF_SIZE ist 1512. Ahhh, da ist ja die 15!  ;)

Scherz beiseite. Das 2. habe ich mittlerweile gefunden (ein else zuviel, 
ich könnte mir in den *** beißen!)
Ich fürchte, mein nächstes Problem ist auch noch so etwas von der Sorte: 
uip_restart() funzt nicht. Es werden weiter fröhlich ZeroWindows 
gesendet, obwohl in uip_conn->tcpconnflags das Pausebit von 
uip_restart() definitiv gelöscht wird. Zumindest der Aufruf scheint also 
stattzufinden.
Jetzt ist aber erstmal Doku-Studieren angesagt, bevor ich mich hier noch 
weiter blamiere!
Langsam fühle ich mich zu doof für Ethernet.  :(

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kurzes Erratum:
UIP_CONF_BUF_SIZE ->UIP_CONF_BUFFER_SIZE
uip_conn->tcpconnflags -> uip_conn->tcpstateflags

Proggen und Internet laufen bei mir in 2 verschiedenen Benutzeraccounts, 
also sorry wegen der Tippfehler!

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andy

>ein else zuviel ?

Das wäre meine nächste Frage gewesen ;-)


Viel Spass noch beim entwanzen deines Codes...

Volker

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für alle, die demnächst am gleichen Problem verzweifeln und noch diesen 
Thread finden, hier die Auflösung des uip_restart()-Problems:

Ich hatte in der Ereignis-Behandlungsroutine des Empfangs pauschal 
uip_stop() aufgerufen, weil ich nach jedem empfangenen Daten-Paket 
erstmal pausieren wollte (recht rudimentäres Puffer-Management, aber für 
diesen Einsatz ausreichend).
Anscheinend wird die Empfangsroutine auch dann aufgerufen, wenn es gar 
keine Daten gibt (z.B. ACK). Folgende Version bei receive funktioniert:
if(datalen > 0) {
  uip_stop();
}

Ein herzliches Danke an Volker für die Inspiration!  ;)

Noch ein schönes Restwochenende!
Andy

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Anscheinend wird die Empfangsroutine auch dann aufgerufen, wenn es gar
>keine Daten gibt (z.B. ACK).

Ja, z.B. alle 0,5s durch das Poll-Ereignis (uip_poll()).

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim Pollen ist das Empfangsflag also auch gesetzt? OK, das habe ich 
mangels JTAG-Debugger nicht extra nachgeschaut.

Meine State-Machine schaut wie folgt aus
inline void AppCall(void)
{
  // Status auswerten
  if(uip_acked()) {            // Daten acknowledged?
    Acked();
  }
  if(uip_rexmit()) {            // Daten neu übertragen?
    Retransmit();
  }
  if(uip_newdata()) {            // Daten empfangen?
    Receive(uip_appdata, uip_datalen());
  }
  if(uip_poll()) {            // Verbindung idle?
    Poll();
  }
  if(uip_connected()) {          // neu verbunden?
    NewConnection();
  }
  if(uip_closed()) {            // Verbindung geschlossen?
    CloseConnection();
  }
  if(uip_aborted()) {            // Verbindung abgebrochen?
    CloseConnection();
  }
}

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Beim Pollen ist das Empfangsflag also auch gesetzt?

Nein, natürlich nicht - ich dachte auch du meintest deine komplette 
Applikation.
Wobei natürlich prinzipiell mehrere Flags gleichzeitig gesetzt sein 
können.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.