Forum: Compiler & IDEs uIP überrannt?


von Andy (Gast)


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

von Volker (Gast)


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!

von Andy (Gast)


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

von Volker (Gast)


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.

von Andy (Gast)


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!

von Andy (Gast)


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

von Volker (Gast)


Lesenswert?

Wie groß ist denn dein uIP-Sende/Empfangspuffer?

von Andy (Gast)


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

von Andy (Gast)


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!

von Volker (Gast)


Lesenswert?

Hallo Andy

>ein else zuviel ?

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


Viel Spass noch beim entwanzen deines Codes...

Volker

von Andy (Gast)


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:
1
if(datalen > 0) {
2
  uip_stop();
3
}

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

Noch ein schönes Restwochenende!
Andy

von Volker (Gast)


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

von Andy (Gast)


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
1
inline void AppCall(void)
2
{
3
  // Status auswerten
4
  if(uip_acked()) {            // Daten acknowledged?
5
    Acked();
6
  }
7
  if(uip_rexmit()) {            // Daten neu übertragen?
8
    Retransmit();
9
  }
10
  if(uip_newdata()) {            // Daten empfangen?
11
    Receive(uip_appdata, uip_datalen());
12
  }
13
  if(uip_poll()) {            // Verbindung idle?
14
    Poll();
15
  }
16
  if(uip_connected()) {          // neu verbunden?
17
    NewConnection();
18
  }
19
  if(uip_closed()) {            // Verbindung geschlossen?
20
    CloseConnection();
21
  }
22
  if(uip_aborted()) {            // Verbindung abgebrochen?
23
    CloseConnection();
24
  }
25
}

von Volker (Gast)


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.

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.