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
>(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!
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...)
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.
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!
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
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. :(
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!
Hallo Andy
>ein else zuviel ?
Das wäre meine nächste Frage gewesen ;-)
Viel Spass noch beim entwanzen deines Codes...
Volker
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
>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()).
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 | }
|
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.