Forum: Mikrocontroller und Digitale Elektronik ENC28J60 liesst falsch Datenpaket aus


von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

Hi Leute,
ich habe folgendes Problem:
für meine Bachelorarbeit baue ich ein Modul, welches mir auf dem I2C Bus 
einkommenden Daten ins Ethernet pusten soll. Dazu habe ich eine Platine 
erstellt, auf der ein Cortex M3 den Ethernetcontroller ENC28J60 
ansteuert.
(Bevor jetzt alle entsetzt den Kopf schütteln: Der Cortex muss sein, da 
ich das Modul in ein größeres System einbauen muss, bei dem ich unter 
anderem mindestens 2 I2c, 2 SPI und 1 CAN Schnittstelle brauche)
Aber, wie auch immer, es geht um den ENC:
Die Platine ist fertig, den ENC kann man wunderbar anpingen, er gibt 
auch Antwort.
Nun möchte ich über Ethernet und TCP/IP Daten auf meinen Rechner 
übertragen.
TCP muss sein, da es bei den Daten um im wahrsten Sinne des Wortes 
Lebenswichtige Daten geht.
Auf meinem Rechner habe ich einen minni Server laufen, der im Moment zu 
Testzwecken nichts anderes macht, als auf Port 4004 auf Daten zu warten.

Zu beginn lasse ich den ENC eine ARP Anfrage an meinem Rechner stellen, 
was auch ohne Probleme funktioniert.
Dann soll der TCP Handshake folgen, da knallts dann.
Das SYN Paket kommt am Rechner an, der Rechner antwortet auch mit Syn 
ACK, aber der ENC füllt jedesmal ein falsches Datenpaket in mein 
Datenbuffer "buf" (ich habe die Stelle im Code gekennzeichnet)
deshalb "spinnt" danach alles, das Programm geht nicht in die 
"Datensendroutine" sondern schickt sofort das FIN Paket. Da aber im 
"buf" falsche werte stehen, meint nun mein Rechner, ein "printer" würde 
anfangen zu senden, und alle sind mords irritiert :(

hier ist mein Code für die Senderoutine (für das erste Paket ist bereits 
ein Ethernet/Ip/TCP Header erstellt, die Header für die Folgepakete 
werden in der Methode tcp_client_send_packet() erstellt):
1
void sendTCPDataToServer(unsigned char *databuf, unsigned int length) {
2
  unsigned int lengthToSend = IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + length
3
      + ETH_HEADER_LEN;
4
  unsigned char sendEtherBuf[lengthToSend];
5
  unsigned int i = 0;
6
  unsigned int plen;
7
8
  tcp_client_send_packet(EthIpTcpHeader, wwwport, sourceport, TCP_FLAG_SYN_V, // flag
9
      1, // (bool)maximum segment size
10
      1, // (bool)clear sequence ack number
11
      0, // 0=use old seq, seqack : 1=new seq,seqack no data : new seq,seqack with data
12
      0, // tcp data length
13
      destinationmacaddr, destinationipaddr, 1);
14
15
  client_state = SYNC_SENT;
16
  //}
17
18
  // get new packet
19
  if (client_state == SYNC_SENT) {
20
  for (int i = 0; i < 500; i++)
21
    buf[i] = 0x0f;
22
23
//HIER WIRD "buf" FALSCH BEFÜLLT----------------------
24
//die routine enc28j60PacketReceive() stimmt aber, da ja das anpingen //funktioniert.......
25
  plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
26
27
28
29
  // no new packet incoming
30
  if (plen == 0) {
31
    return;
32
  }
33
 }
34
35
36
37
  // check SYNACK flag, after cortex send SYN, server response by send SYNACK to AVR
38
39
//da buf nicht die Werte TCP_FLAG_SYN_V | TCP_FLAG_ACK_V anzeigt, geht das 
40
//Programm hier erst gar nicht hinein
41
  if (buf[TCP_FLAGS_P] == (TCP_FLAG_SYN_V | TCP_FLAG_ACK_V)) {
42
43
    // send ACK to answer SYNACK
44
45
    tcp_client_send_packet(buf, wwwport, sourceport, TCP_FLAG_ACK_V, // flag
46
        0, // (bool)maximum segment size
47
        0, // (bool)clear sequence ack number
48
        1, // 0=use old seq, seqack : 1=new seq,seqack no data : new seq,seqack with data
49
        0, // tcp data length
50
        destinationmacaddr, destinationipaddr, 0);
51
    
52
    //fill in the Data Bytes
53
    while (i < length) {
54
      buf[TCP_DATA_P + i] = databuf[i];
55
      i++;
56
    }
57
    tcp_client_send_packet(buf, wwwport, // destination port
58
        sourceport, TCP_FLAG_ACK_V | TCP_FLAG_PUSH_V, // flag
59
        0, // (bool)maximum segment size
60
        0, // (bool)clear sequence ack number
61
        0, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
62
        plen, // tcp data length
63
        destinationmacaddr, destinationipaddr, 0);
64
    //return;
65
  }
66
67
68
  // send finack to disconnect from web server
69
70
  tcp_client_send_packet(buf, wwwport, // destination port
71
      sourceport, // source port
72
      TCP_FLAG_FIN_V | TCP_FLAG_ACK_V, // flag
73
      0, // (bool)maximum segment size
74
      0, // (bool)clear sequence ack number
75
      0, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
76
      0, destinationmacaddr, destinationipaddr, 0);
77
78
  plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
79
80
  // answer FINACK from web server by send ACK to web server
81
  if (buf[TCP_FLAGS_P] == (TCP_FLAG_ACK_V | TCP_FLAG_FIN_V)) {
82
    // send ACK with seqack = 1
83
    tcp_client_send_packet(
84
85
    buf, wwwport, // destination port
86
        sourceport, // source port
87
        TCP_FLAG_ACK_V, // flag
88
        0, // (bool)maximum segment size
89
        0, // (bool)clear sequence ack number
90
        1, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
91
        0, destinationmacaddr, destinationipaddr, 0);
92
    client_state = IDLE; // return to IDLE state
93
    client_data_ready = 0; // client data sent
94
  }
95
96
}

Was eigendlich in buf stehen sollte, ist in der angehängten Wireshark 
Messung zu sehen,
hier ist das, was in buf steht:
00 01 02 03 04 05 00 11   25 d5 cd de 08 06 00 01
08 00 06 04 00 02 00 11   25 d5 cd de c0 a8 01 02
00 01 02 03 04 05 c0 a8   01 0f

Die ersten 13 Werte stimmen, aber dann kommt eine angeblich ARP Antwort, 
und der Rest ist eigendlich nur  noch Mist.....

hier die tcp_client_send_packet() Routine:
1
void tcp_client_send_packet(unsigned char *buf, unsigned int dest_port,
2
    unsigned int src_port, unsigned char flags,
3
    unsigned char max_segment_size, unsigned char clear_seqack,
4
    unsigned int next_ack_num, unsigned int dlength,
5
    unsigned char *dest_mac, unsigned char *dest_ip,
6
    unsigned int isFirstPackage) {
7
  unsigned char i = 0;
8
  unsigned char tseq;
9
  unsigned int ck;
10
11
  if (!isFirstPackage)
12
    make_eth_ip_new(buf, dest_mac);
13
14
  //  buf[TCP_DST_PORT_H_P]= (unsigned char) ( (dest_port>>8) & 0xff);
15
  //  buf[TCP_DST_PORT_L_P]= (unsigned char) (dest_port & 0xff);
16
17
  //  buf[TCP_SRC_PORT_H_P]= (unsigned char) ( (src_port>>8) & 0xff);
18
  //  buf[TCP_SRC_PORT_L_P]= (unsigned char) (src_port & 0xff);
19
20
  // sequence numbers:
21
  // add the rel ack num to SEQACK
22
23
  if (next_ack_num) {
24
    for (i = 4; i > 0; i--) {
25
      next_ack_num = buf[TCP_SEQ_H_P + i - 1] + next_ack_num;
26
      tseq = buf[TCP_SEQACK_H_P + i - 1];
27
      buf[TCP_SEQACK_H_P + i - 1] = 0xff & next_ack_num;
28
      // copy the acknum sent to us into the sequence number
29
      buf[TCP_SEQ_P + i - 1] = tseq;
30
      next_ack_num >>= 8;
31
    }
32
  }
33
34
  // initial tcp sequence number,require to setup for first transmit/receive
35
  if (max_segment_size) {
36
    // put inital seq number
37
    buf[TCP_SEQ_H_P + 0] = 0;
38
    buf[TCP_SEQ_H_P + 1] = 0;
39
    // we step only the second byte, this allows us to send packts
40
    // with 255 bytes or 512 (if we step the initial seqnum by 2)
41
    buf[TCP_SEQ_H_P + 2] = seqnum;
42
    buf[TCP_SEQ_H_P + 3] = 0;
43
    // step the inititial seq num by something we will not use
44
    // during this tcp session:
45
    seqnum += 2;
46
47
    // setup maximum segment size
48
    buf[TCP_OPTIONS_P] = 2;
49
    buf[TCP_OPTIONS_P + 1] = 4;
50
    buf[TCP_OPTIONS_P + 2] = 0x05;
51
    buf[TCP_OPTIONS_P + 3] = 0x80;
52
    // 24 bytes:
53
    buf[TCP_HEADER_LEN_P] = 0x60;
54
55
    dlength += 4;
56
  } else {
57
    // no options:
58
    // 20 bytes:
59
    buf[TCP_HEADER_LEN_P] = 0x50;
60
  }
61
62
  make_ip_tcp_new(buf, IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlength,
63
      dest_ip);
64
65
  // clear sequence ack numer before send tcp SYN packet
66
  if (clear_seqack) {
67
    buf[TCP_SEQACK_P] = 0;
68
    buf[TCP_SEQACK_P + 1] = 0;
69
    buf[TCP_SEQACK_P + 2] = 0;
70
    buf[TCP_SEQACK_P + 3] = 0;
71
  }
72
  // zero the checksum
73
  buf[TCP_CHECKSUM_H_P] = 0;
74
  buf[TCP_CHECKSUM_L_P] = 0;
75
76
  // set up flags
77
  buf[TCP_FLAG_P] = flags;
78
  // setup maximum windows size
79
  buf[TCP_WINDOWSIZE_H_P] = ((600 - IP_HEADER_LEN - ETH_HEADER_LEN) >> 8)
80
      & 0xff;
81
  buf[TCP_WINDOWSIZE_L_P] = (600 - IP_HEADER_LEN - ETH_HEADER_LEN) & 0xff;
82
83
  // setup urgend pointer (not used -> 0)
84
  buf[TCP_URGENT_PTR_H_P] = 0;
85
  buf[TCP_URGENT_PTR_L_P] = 0;
86
87
  // check sum
88
  ck = checksum(&buf[IP_SRC_P], 8 + TCP_HEADER_LEN_PLAIN + dlength, 2);
89
  buf[TCP_CHECKSUM_H_P] = ck >> 8;
90
  buf[TCP_CHECKSUM_L_P] = ck & 0xff;
91
  // add 4 for option mss:
92
  enc28j60PacketSend(
93
      IP_HEADER_LEN + TCP_HEADER_LEN_PLAIN + dlength + ETH_HEADER_LEN,
94
      buf);
95
96
}

Die Methode  enc28j60PacketReceive() habe ich, genauso wie die 
initialisierung des ENC aus der im Internet erhältlichen Library für den 
ENC. Aber die müssten ja stimmen, da ja wie gesagt, das anpingen 
funktioniert.
Hat jemand eine Ahnung, warum in buf in meiner TCP Routine nun aber 
falsche Werte stehen?
Danke schonmal
Sylvia

von Sylvia H. (sandy)


Lesenswert?

ich habe jetzt mal versucht, meine Daten per UDP zu versenden, das wird 
noch seltsamer:
Obwohl ich das Datenpaket richtig gefüllt habe (Ethernet, IPO,Udp Header 
+ Daten) sendet der ENC das Paket falsch raus:
Ich habe 2 Rechner, einmal ein Linux und einmal ein Windows 7 Rechner.
Auf dem Linux Rechner zeigt mir der Wiresharc es käme ein "Bogus IP 
Header Length" Paket an d.h. der Wert für IP Header Length sei 0. Dabei 
ist er in meinem Datenpaket richtig gesetzt! (Zumindest zeigt mir 
Eclipse das im Debugmode so an)
Und auf dem Windows Rechner wird im Wiresharc schon mal überhaupt nix 
angezeigt...(die Verbindung ist aber da, man kann den ENC anpingen, das 
zeigt mir auch der Wiresharc)
Ich brauch dringend einen Rat!

von Tiramisu (Gast)


Lesenswert?

>Ich brauch dringend einen Rat!
Solche TCP/IP Stacks werden von den Layern von unten aufwaerts entwanzt.

Physik: Erstmal: Wieviel Erfahrung hast Du im Platinendesign? 100nF an
allen Ecken und Enden? Leitungen kurz und mit Masse nicht gespart?
Welcher Takt? Schon mal andere "groessere" Programme fehlerfrei mit
der Platine laufen lassen?

>> enc28j60.c
> wait(unsigned int time) {for (int i = 0; i < time; i++) { }
Du verwendest gcc? Was meinst Du passiert damit?
Du verwendest eine Library, die fuer einen AVR gemacht wurde und
nun fuer eine ARM-Architektur eingesetzt wird?
>>enc28j60PhyWrite
>//_nop_();
So ein NOP koennte schon Sinn machen?
Solche Uebertaktungen koennen zu 99,9% der Bituebertragungen gutgehen;
doch das ist zu wenig. Bitte die anliegenden Taktfrequenzen mittels
eines Speicheroskars/Logikanalyzers und dem Datanblatt checken
und sklavisch ans Datenblatt (und den ENC-Erratas) halten!
Und beim ENC gibt es HW-Revisions mit mehr und weniger Fehlern...

>Was eigendlich in buf stehen sollte, ist in der angehängten Wireshark
>Messung zu sehen,
>hier ist das, was in buf steht:
>00 01 02 03 ...
Da steht ein ARP drin, was haettest Du erwartet?
Aus der Auffassung, dass ping funktioniert, implizierst Du, dass der
IP-Stack/Layer-3 in Ordnung ist, richtig? Ansonsten irgendwelche
L3-Tests gemacht?
Wie misst Du? Mit einem Crosskabel oder einem Hub?
Du siehst auf dem Windows pings
zurueckkommen, aber nichts mit dem Wireshark? Irgendwo bei Linux
dann mal CRC-Fehler gesehen?
Zuviele Ungereimtheiten, wenn die "Messgeraete" dann noch unlogisch 
sind!

Layer4:
Ich wuerde mit UDP zum Debuggen weitermachen, weil das
das viel einfachere Protokoll ist auf Layer4 ist. (Fuer die 
PC-Gegenstelle
verwendet man nicht irgendwas Selbstgestricktes, sondern netcat oder 
socat).

Aus dem wireshark:
Ich koennte wetten, dass der Fehler schon beim Empfangsbearbeiten
von Wireshark Paket 4 auftritt, denn Dein Programm wechselt ploetzlich
den Port auf "printer". Da muss schon etwas nicht stimmen. Das RST
Paket ist die ganz normale Reaktion Deines Rechners auf eine
vom ARM unterstellte Kommunikationsbeziehung, die Dein Rechner
nicht kennt.
Normalerweise ist das dritte Paket ein ACK; das FIN deutet darauf hin, 
dass der
ARM nach der vermeindlich fehlerhaften Empfangsbearbeitung (eigentlich) 
nach
Protokolspec. ein RST haette schicken muessen... aber man hat gespart
und wohl Code reused. (Alle der kleinen embedded TCP/IP Stacks haben
massive Ungereimtheiten aka Vereinfachungen)

Was sagt denn Dein Betreuer zu den Problemen?

>im wahrsten Sinne des Wortes Lebenswichtige Daten geht
Wenn es um sowas geht, wuerde ich einen TCP/IP Stack verwenden, der
x*100Mio-man im Feld ist. Embedded (uC-)Linux Boards gibts viele...
Ich habe S7-Steuerungen gesehen, die "nur" millionenmal im Feld sind,
wobei deren TCP-Stacks bei gewissen IP-Options nach genau 512kB
TCP-Datenuebertragungen crashen...

Tiramisu

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

wow, das ist mal eine Antwort, ich dachte schon, alle die Ahnung haben 
sind zur Zeit auf Urlaub ;) Danke schonmal !!!!!


> Physik: Erstmal: Wieviel Erfahrung hast Du im Platinendesign? 100nF an
> allen Ecken und Enden? Leitungen kurz und mit Masse nicht gespart?
> Welcher Takt? Schon mal andere "groessere" Programme fehlerfrei mit
> der Platine laufen lassen?

Die Leiterplatte ist zweiseitig, und hat auf beiden Seiten eine GND 
Plane.
Vom Schaltplan habe ich die Seite mit dem ENC angehängt, wobei 
SS,MISI,NOSI und SCK Verbindung mit er ersten Schaltplanseite haben, 
also mit den entsprechenden Ausgängen des Cortex M3.
Einen groben Fehler habe ich nach tagelanger Suche entdeckt: Die Eagle 
Lib für den ENC ist Falsch, die Anschlüsse für den Quarz sind verdreht. 
Mann kann sich wohl auf nichts verlassen, noch nicht einmal auf CadSoft. 
Also musste ich Leiterbahnen mit dem Skalpell aufkratzen und Beinchen 
des ENC hochbiegen, und mit haarfeinen kurzen drähtchen die Verbindungen 
korrigieren. Den Quarz hatte ich auch schon ausgetauscht, ich hatte zu 
Beginn einen Obertonquarz und jetzt einen xxs Grundtonquarz (auch mit 
feinen Drähtchen ) eingebaut.
Der Cortex läuft auf 32 Mhz, die SPI Taktung der ENC Ansteuerung auf 8 
MHz


> Du verwendest gcc? Was meinst Du passiert damit?
 die Frage versteh ich nicht....
> Du verwendest eine Library, die fuer einen AVR gemacht wurde und
> nun fuer eine ARM-Architektur eingesetzt wird?
Damit müsste doch eine ARM auch zurechtkommen?


>>>enc28j60PhyWrite
>>//_nop_();
> So ein NOP koennte schon Sinn machen?
> Solche Uebertaktungen koennen zu 99,9% der Bituebertragungen gutgehen;
> doch das ist zu wenig. Bitte die anliegenden Taktfrequenzen mittels
> eines Speicheroskars/Logikanalyzers und dem Datanblatt checken
> und sklavisch ans Datenblatt (und den ENC-Erratas) halten!
> Und beim ENC gibt es HW-Revisions mit mehr und weniger Fehlern...
verstehe ich das richtig, man muss dem ENC mehr Zeit zum Auslesen geben?


> Da steht ein ARP drin, was haettest Du erwartet?
Ich erwarte, das in buf nun Datenpaket 4 aus der Wiresharkmessung steht, 
da dies das Paket ist, das der ENC nach seinem SYN Paket empfängt.


> Wie misst Du? Mit einem Crosskabel oder einem Hub?
> Du siehst auf dem Windows pings
> zurueckkommen, aber nichts mit dem Wireshark? Irgendwo bei Linux
> dann mal CRC-Fehler gesehen?

Ich habe das ENC Board mit einem Crossover Kabel direkt an meine Rechner 
angeschlossen, CRC Fehler waren nie zu sehen. Die Ping Pakete hat 
Wireshark auf dem Windows Rechner alle angezeigt, er streikte nur bei 
den UDP Paketen, und gibt mir kein ACK als Antwort auf meine SYN Anfrage


> Ich koennte wetten, dass der Fehler schon beim Empfangsbearbeiten
> von Wireshark Paket 4 auftritt, denn Dein Programm wechselt ploetzlich
> den Port auf "printer". Da muss schon etwas nicht stimmen.

ganz genau !
Der ENC liest ein falsches Datenpaket aus, er müsste eigendlich Paket 4 
dem Cortex weitersenden, tut es aber nicht....

> Was sagt denn Dein Betreuer zu den Problemen?

Mein Betreuer ist leider der Meinung, er möchte keine Probleme sehen, 
sondern Lösungen. Daher habe ich ihm noch nichts gesagt..........

Genauso wie der ENC ein falsches Datenpaket aus seinem EmpfangsFifo 
holt, so scheint er auch die UDP Pakete falsch zu versenden. Ich habe 
das UDP Paket genau beobachtet, bis zu dem Zeitpunkt bei dem das Paket 
in das SendeFifo geschrieben wird ist es richtig gefüllt.
Aber Anscheinend schickt der ENC danach ein falsches Paket ins Ethernet.
Könnte es vielleicht sein, das der ENC auch zum Schreiben mehr zeit 
braucht, und ein kleinens delay eingeführt werden muss?
Leider kann ich das erst am Montag morgen ausprobieren, um Moment bin 
ich zuhause und schreibe an meiner Doku.
Gruß
Sylvia

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

>> Du verwendest eine Library, die fuer einen AVR gemacht wurde und
>> nun fuer eine ARM-Architektur eingesetzt wird?
> Damit müsste doch eine ARM auch zurechtkommen?

Deine Delay-Routine könnte je nach Compiler und Optimierungseinstellung 
gut und gern keinerlei Delay bewirken - und mit Sicherheit nicht das was 
dransteht.

Bei ARMs sind Delay-Schleifen ohne Laufzeitkalibrierung höchst unsichere 
Genossen, selbst wenn sie vom Compiler nicht wegoptimiert werden, weil 
abhängig nicht nur vom Modell, sondern auch vom Speicherort (RAM, Flash) 
und von der exakten Adresse (fetch alignment).

von Sylvia H. (sandy)


Lesenswert?

das mit der falschen Dealyroutine habe ich noch nie gehört, es ist das 
erste Mal, das ich mit dem Cortex arbeite. Bisher habe ich immer mit 
Atmegas oder ATXmegasS gearbeitet.
Muss mich da mal genauer informieren...
Danke

von Tiramisu (Gast)


Lesenswert?

>Die Leiterplatte ist zweiseitig, und hat auf beiden Seiten eine GND
>Plane.
und viele viele 100nF? Der ENC zieht im ns-Bereich ganz gehoerig...

>Damit müsste doch eine ARM auch zurechtkommen?
Bytesex, 8/16-Bit auf 32 Bit-Probleme... also ganz ehrlich: ich mache
solche Sachen auch seit den 80ern und hatte noch nie Glueck,
dass ein 8/16-Bit Programm ohne Fixes auf einem 32-Bit System lief.
Meine EInschaetzung waere, dass ich eher einen Volltreffer
im Lotto lande...

> die Anschlüsse für den Quarz sind verdreht.
Aehmm, wieso?

> die Frage versteh ich nicht....
Neben den obigen Problemen kommt es massiv auf den C-Compiler
an. Einige Compiler (gcc) optimieren so stark, dass sie die Delay 
Routine
einfach wegoptimieren. Daher die -- zugegebenermassen  indirekte
Frage nach dem C-Compiler...

>Ich habe das ENC Board mit einem Crossover Kabel direkt an meine Rechner
>angeschlossen, CRC Fehler waren nie zu sehen. Die Ping Pakete hat
>Wireshark auf dem Windows Rechner alle angezeigt, er streikte nur bei
>den UDP Paketen, und gibt mir kein ACK als Antwort auf meine SYN Anfrage

Bei UDP gibt es kein SYN/ACK.
Zeig mal einen (UDP-)Wireshark, stelle bitte die "Intelligenz" 
(Numerisches
Anzeigen der Ports z.B.) aus. Es ist problematisch, wenn man dann
noch Unsicherheit bei Analysetools hat; das ist wie ein Gleichungssystem
mit 5 Unbekannten loesen anstatt einer Unbekannten. Es gibt beim ENC
Unschoenheiten beim half/full-duplex Negotiation und einigen
Netzwerkkarten. Daher: in der Bastelkiste wird sich hoffentlich irgendwo
noch ein (halfduplex) Hub finden, nimm' dies zum Debuggen.
Der Vorteil daran ist, dass man auf einem Linux-Rechner 
tcpdumpen/wiresharken
und an einem anderen Rechner die Produktions-SW hat.
Hast Du ein Oskar und ein Logikanalyzer zur Hand?

Tiramisu

von Tiramisu (Gast)


Lesenswert?

Sorry, noch eine kleine Anmerkung, ich bin normalerweise
kein Rechtschreib-Haarspalter: "eigendlich" bitte mit "t" schreiben. 
Wenn ich
noch mehrmals den Text lesen sollte, werde ich das Wort auch falsch
schreiben :-)

Tiramisu

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

> und viele viele 100nF? Der ENC zieht im ns-Bereich ganz gehoerig...

3x 100 nF, ich weis, ich hätte vielleicht 5x 100 nF nehmen sollen, für 
jeden VDD anschluss einen eigenen 100 nF..

> Bytesex, 8/16-Bit auf 32 Bit-Probleme...
davon habe ich leider noch nie etwas gehört, ich programmiere erst seit 
2 Jahren Mikrocontroller und bisher immer nur 8/16 Bit Controller sorry 
;(


>> die Anschlüsse für den Quarz sind verdreht.
> Aehmm, wieso?
Die Eagle Lib von CasSoft war falsch: VDDOSC muss auf Pin 22, OSC1 auf 
Pin 23, OSC2 auf Pin 24, VSSOSC auf Pin 22


> Daher die -- zugegebenermassen  indirekte
> Frage nach dem C-Compiler...
Ich compilliere das Programm in Eclipse. Die Delay Routine funktioniert 
eigentlich, ich hatte bei der Entwicklung dieser Routine eine Pin 
toggeln lassen, und mit dem Oszi herausgefunden, das wenn man einen Wert 
von 720 eingibt, der Pin mit 1 ms getoggelt wird.


> Bei UDP gibt es kein SYN/ACK.
Entschuldige, da habe ich mich wohl falsch ausgedrückt. Natürlich gibt 
es bei UDP keinen 3-Way Handshake. Ich wollte nur sagen, das bei der TCP 
Übertragung mein Linux Rechner ein SYNC ACK schickt und der Windows 
Rechner nicht. Wenn ich versuchsweise meine Daten per UDP verschicken 
möchte, dann zeigt mein Linux Wireshark das Datenpaket (7) wie in der 
Angehängten png, der Windows Wireshark zeigt überhaupt nichts an.
Und das, obwohl ich das UDP Datenpaket richtig gefüllt habe. dies kann 
ich mit Eclipse bis zum Versenden mit enc28j60PacketSend() schön 
beobachten.

Einen Oscar habe ich auf der Arbeit, aber leider keinen Logicanalyzer

Sylvia

von Tiramisu (Gast)


Lesenswert?

>Die Delay Routine funktioniert
>eigentlich, ich hatte bei der Entwicklung dieser Routine eine Pin
>toggeln lassen, und mit dem Oszi herausgefunden, das wenn man einen Wert
>von 720 eingibt, der Pin mit 1 ms getoggelt wird.

Wenn der Pin-Toggle jetzt nicht mehr drinsteht, dann optimiert
der GCC Compiler die for()-Schleife weg.

von Tiramisu (Gast)


Lesenswert?

>Ich wollte nur sagen, das bei der TCP
>Übertragung mein Linux Rechner ein SYNC ACK schickt und der Windows
>Rechner nicht.

Genau, bereits dafuer muss es einen Grund geben!! Ich gehe davon aus,
dass Du bei den ganzen Voraussetzungen nicht einen, sondern ein halbes
Dutzend Fehler auf unterschiedlichen Layern eliminieren musst.

Das Ausbleiben des SYN/ACKs liegt vermutlich darin, dass noch irgendwas
in einem Layer < 4 nicht stimmt (wenn es nun nicht etwas ist, was in dem
Windows(Firewall..) oder dem dazugehörenden Admin begründet ist ;-)!

Jedenfalls ein Ansatzpunkt, um nicht gleich beim Debuggen in die
wesentlich kompliziertere TCP-Routine reingehen zu muessen.
(Wie gesagt, ich wuerde ein Hub verwenden)

von Tiramisu (Gast)


Lesenswert?

Weitere Tipps:
- auf die Mindestlaenge von 64 Byte Ethernetframe achten.
- UDP-Wireshark: Dort wo beim UDP-Packet der IP Header stehen sollte,
   ist 0x00, 01, 02,...,0x0f zu finden. Es sieht aus, als waere die 
Laufvariable
   da hineinkopiert worden...

von ... (Gast)


Lesenswert?

Pin5, RCT, des Modular-Jack darf nicht angeschlossen sein.

von ... (Gast)


Lesenswert?

Sylvia H. schrieb:
> Einen groben Fehler habe ich nach tagelanger Suche entdeckt: Die Eagle
> Lib für den ENC ist Falsch, die Anschlüsse für den Quarz sind verdreht.

In deinem jetzigen Schaltbild ist ein grober Fehler:
Die Osc.-Anschlüsse sind lt. Datenblatt beim SO-Gehäuse Pin 23 und 24, 
nicht wie in deinem Schaltbild Pin 22 und 23.

von ... (Gast)


Lesenswert?

... schrieb:
> Pin5, RCT, des Modular-Jack darf nicht angeschlossen sein.

Das wird ua. auch der Grund sein warum dein ENC so heiß wird.

von Sylvia H. (sandy)


Lesenswert?

... schrieb:
> In deinem jetzigen Schaltbild ist ein grober Fehler:
> Die Osc.-Anschlüsse sind lt. Datenblatt beim SO-Gehäuse Pin 23 und 24,
> nicht wie in deinem Schaltbild Pin 22 und 23.

ich weis, das habe ich schon korrigiert, da war die Eagle Lib falsch, 
siehe im Text weiter oben.......

... schrieb:
> Pin5, RCT, des Modular-Jack darf nicht angeschlossen sein.

warum denn nicht ?????????

Tiramisu schrieb:
> - UDP-Wireshark: Dort wo beim UDP-Packet der IP Header stehen sollte,
>    ist 0x00, 01, 02,...,0x0f zu finden. Es sieht aus, als waere die
> Laufvariable
>    da hineinkopiert worden...

Das sind meine Test Nutzerdaten. das ist es ja gerade, ich habe das UDP 
Paket richtig gepackt, aber der ENC schickt es falsch fort.......

von ... (Gast)


Lesenswert?

Sylvia H. schrieb:
> ... schrieb:
>
>> Pin5, RCT, des Modular-Jack darf nicht angeschlossen sein.
>
> warum denn nicht ?????????

Vergleich doch mal die Applikationsschaltung im Datenblatt des ENCs mit 
der Innenbeschaltung deines Modular-Jacks. Fällt dir da was auf?

Sylvia H. schrieb:
> ich weis, das habe ich schon korrigiert,

Ja wie, und da hälst du es nicht für nötig, das Schaltbild mal zu 
korrigieren bevor du es hier postest und um Hilfe bittest?

von Sylvia H. (sandy)


Lesenswert?

... schrieb:
> Vergleich doch mal die Applikationsschaltung im Datenblatt des ENCs mit
> der Innenbeschaltung deines Modular-Jacks. Fällt dir da was auf?

ok, habs gesehen, danke für den Tip

... schrieb:
> Ja wie, und da hälst du es nicht für nötig, das Schaltbild mal zu
> korrigieren bevor du es hier postest und um Hilfe bittest?

Entschuldige, ich bin im moment ein wenig überfordert mit der ganzen 
Thematik, da hatte ich noch keine Zeit die Eagle Lib zu ändern....
Aber ich habs ja gepostet, das ich die Leiterbahnen aufgeschnitten, die 
Beinchen hochgebogen, und alles mit feinen Drähtechen korrigiert habe

siehe:
Sylvia H. schrieb:
> Einen groben Fehler habe ich nach tagelanger Suche entdeckt: Die Eagle
> Lib für den ENC ist Falsch, die Anschlüsse für den Quarz sind verdreht.
> Mann kann sich wohl auf nichts verlassen, noch nicht einmal auf CadSoft.
> Also musste ich Leiterbahnen mit dem Skalpell aufkratzen und Beinchen
> des ENC hochbiegen, und mit haarfeinen kurzen drähtchen die Verbindungen
> korrigieren.


Ich habe mal die Wartefunktion in enc28j60.c abgeändert:
1
/*
2
 * Methode sorgt für eine Wartezeit
3
 * @param time Die Wartezeit, wobei ein Wert von 720 = 1ms entspricht
4
 */
5
void wait(unsigned int time) {
6
  while (time) {
7
    time--;
8
  }

und bei der Initialisierung des ENC nach dem dem System Reset auch noch 
eine Wartezeit eingebaut :
1
enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
2
//  Del_1ms(250);
3
  wait(180000);
da ich in einem Beitrag hier im Forum gelesen hatte der ENC braucht dies 
um korrekt zu arbeiten.
Und siehe da:
DAS UDP PAKET WIRD NUN RICHTIG VERSCHICKT !!!!! HURRA !!


Ich werd mich gleich mal dranmachen, und Pin 5 "befreien", mal sehn obs 
dann auch mit der TCP Verbindung funzt.......

von Sylvia H. (sandy)


Lesenswert?

funzt leider nicht, mal weitersuchen.....

von Tiramisu (Gast)


Lesenswert?

>void wait(unsigned int time) {
>  while (time) {
>    time--;
>  }

Schau mal bitte im Assemblercode, ob da nicht
einfach ein Ruecksprung steht...

Falls der "Togglepin" noch frei ist, nimm testhalber
dieses togglen mit in die wait()-Routine.

von Sylvia H. (sandy)


Lesenswert?

war wohl nix mit freuen :(
UDP Pakete kommen nur richtig an, wenn man vorher einen (erfolglosen!) 
Versuch gestartet hat, eine TCP Verbindung auf zu bauen.
Ohne diesen Versuch kommt immer nur ein "bogus IP Header length" Paket 
an, wie auf der Wireshark Messung von oben.
Ich versteh langsam gar nichts mehr,
ich dacht immer, UDP Pakete kann man verbindungslos schicken......

von ... (Gast)


Lesenswert?

Man soll ja nichts unversucht lassen: Ersetze mal R23 und R18 gegen 470 
Ohm-Widerstände. Evtl. erkennt er die LEDs nicht richtig und setzt das 
PDPXMD bit in einen falschen Zustand, da 1K recht hoch sind als 
Vorwiderstand.
Weiter würde ich diese 10µH-Spule L4 gegen ein Ferrite-Bead tauschen, 
oder wenn du keins da, hast einfach brücken.
C16 und C14 gegen 100nF tauschen.

von ... (Gast)


Lesenswert?

BTW. mit welcher Versorgungsspannung arbeitet dein Cortex M3 ?

von Sylvia H. (sandy)


Lesenswert?

... schrieb:
> BTW. mit welcher Versorgungsspannung arbeitet dein Cortex M3 ?

+3,3V

von ... (Gast)


Lesenswert?

ok, eine Fehlerquelle weniger ;)

von Tiramisu (Gast)


Lesenswert?

>Ohne diesen Versuch kommt immer nur ein "bogus IP Header length" Paket
>an, wie auf der Wireshark Messung von oben.
>Ich versteh langsam gar nichts mehr,

Ich schon, aber ich hab's schonmal geschrieben:

ANSTATT eines IP-Headers stehen im UDP Paket Deine Nutzdaten.
Das IP-Paket muesste mit 0x45 losgehen (sofern keine IP-Options
verwendet werden; die 0x4? bedeutet IPv4... siehst Du die?)

Du musst den Layer3-Code ansehen, da stimmt was nicht!

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

So fülle ich den Ethernet + IP Header:
1
void makeDataSendHeader() {
2
  //  ---------------  ETHERNET HEADER ----------------
3
  int i = 0;
4
  //fill in Destination MAC Adresse
5
  while (i < 6) {
6
    EthIpHeader[ETH_DST_MAC + i] = destinationmacaddr[i];
7
    i++;
8
  }
9
  i = 0;
10
  //fill in Source MAC Adresse
11
  while (i < 6) {
12
    EthIpHeader[ETH_SRC_MAC + i] = macaddr[i];
13
    i++;
14
  }
15
16
  //fill in Type = IP
17
  EthIpHeader[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
18
  EthIpHeader[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
19
20
  // -------------- IPHEADER ----------------------
21
22
  //set Type of Service to default
23
  EthIpHeader[IP_TOS_P] = 0x00;
24
25
  // set packet identification
26
  EthIpHeader[IP_ID_H_P] = (ip_identifier >> 8) & 0xff;
27
  EthIpHeader[IP_ID_L_P] = ip_identifier & 0xff;
28
  ip_identifier++;
29
30
  // set fragment flags
31
  EthIpHeader[IP_FLAGS_H_P] = 0x00;
32
  EthIpHeader[IP_FLAGS_L_P] = 0x00;
33
34
  // set Time To Live
35
  EthIpHeader[IP_TTL_P] = 128;
36
37
  // set ip packettype to tcp/udp/icmp...
38
  EthIpHeader[IP_PROTO_P] = IP_PROTO_TCP_V;
39
40
  //set source/destiantion adresse
41
  i = 0;
42
  while (i < 4) {
43
    EthIpHeader[IP_SRC_P + i] = ipaddr[i];
44
    EthIpHeader[IP_DST_P + i] = destinationipaddr[i];
45
    i++;
46
  }
47
48
  //calculate checksum
49
  fill_ip_hdr_checksum((unsigned char *) EthIpHeader);
50
  fill_ip_hdr_checksum(EthIpHeader);
51
52
}

Danach wird das UDP Paket geschnürt:
1
void sendUdpDataToServer(unsigned char *data, unsigned int datalen)
2
{
3
  unsigned char i = 0;
4
    unsigned int ck;
5
6
  // set ip packettype to tcp/udp/icmp...
7
  EthIpHeader[IP_PROTO_P] = IP_PROTO_UDP_V;
8
  // total length field in the IP header must be set:
9
  EthIpHeader[IP_TOTLEN_H_P] = 0;
10
  EthIpHeader[IP_TOTLEN_L_P] = IP_HEADER_LEN + UDP_HEADER_LEN + datalen;
11
  fill_ip_hdr_checksum(EthIpHeader);
12
  EthIpHeader[UDP_DST_PORT_H_P] = wwwport >> 8;
13
  EthIpHeader[UDP_DST_PORT_L_P] = wwwport & 0xff;
14
    // source port does not matter and is what the sender used.
15
    // calculte the udp length:
16
  EthIpHeader[UDP_LEN_H_P] = 0;
17
  EthIpHeader[UDP_LEN_L_P] = UDP_HEADER_LEN + datalen;
18
    // zero the checksum
19
  EthIpHeader[UDP_CHECKSUM_H_P] = 0;
20
  EthIpHeader[UDP_CHECKSUM_L_P] = 0;
21
    // copy the data:
22
    while (i < datalen) {
23
      EthIpHeader[UDP_DATA_P + i] = data[i];
24
      i++;
25
    }
26
    ck = checksum(&EthIpHeader[IP_SRC_P], 16 + datalen, 1);
27
    EthIpHeader[UDP_CHECKSUM_H_P] = ck >> 8;
28
    EthIpHeader[UDP_CHECKSUM_L_P] = ck & 0xff;
29
    enc28j60PacketSend(
30
        UDP_HEADER_LEN + IP_HEADER_LEN + ETH_HEADER_LEN + datalen, EthIpHeader);
31
32
}
ich habe alles schon zigmal überprüft, die #defines haben die richtigen
Werte, (stehen alle in net.h) das UDP Paket ist richtig geschnürt, aber 
trotzdem sendet der
ENC Mist.....(bzw. die Nutzdaten anstatt des IP Headers)

von Tiramisu (Gast)


Lesenswert?

>das UDP Paket ist richtig geschnürt
Will heissen? Ich interpretiere es mal so:
  Du hast mit dem GDB einen Breakpoint vor enc28j60PacketSend(..)
  in sendUdpDataToServer() gesetzt (bzw. mit einer kleinen
  Routine die Werte ausgegeben, die in EthIpHeader[] stehen)
  und gesehen, dass der zusammengebastelte Buffer gut aussieht?

von Sylvia H. (sandy)


Lesenswert?

Tiramisu schrieb:
> Will heissen? Ich interpretiere es mal so:
>   Du hast mit dem GDB einen Breakpoint vor enc28j60PacketSend(..)
>   in sendUdpDataToServer() gesetzt (bzw. mit einer kleinen
>   Routine die Werte ausgegeben, die in EthIpHeader[] stehen)
>   und gesehen, dass der zusammengebastelte Buffer gut aussieht?

ganz genau, mit dem Eclipse debugger kann man sich wunderbar alle 
Variablen anzeigen lassen. Zum Zeitpunkt des Befehles 
enc28j60PacketSend(..) ist das Datenpaket exact gefüllt. Mit Ethernet 
Header, richtigen IP Header, UDP Header und den Nutzdaten.

von ... (Gast)


Lesenswert?

schon mal dran gedacht, das durch die verschiedenen Schaltungsfehler in 
der Vergangenheit, der ENC mittlerweile den Dienst quittiert hat?

von Sylvia H. (sandy)


Lesenswert?

... schrieb:
> schon mal dran gedacht, das durch die verschiedenen Schaltungsfehler in
> der Vergangenheit, der ENC mittlerweile den Dienst quittiert hat?

was uns nicht tötet macht uns nur härter ;). Der ENC hat gefälligst 
durchzuhalten.....

von Tiramisu (Gast)


Lesenswert?

Bitte einen Breakpoint in enc28j60WriteBuffer() vor sendSPI(*data++)
data setzen, ALLE Bufferinhalte kontrollierend durchsteppen und dann
schauen ob da alles uebertragen wird (d.h. ob dann genuegend
haendische Verzoegerung war :-) um ein ordentliches UDP-Paket
zu schicken.

> schon mal dran gedacht, das durch die verschiedenen Schaltungsfehler in
> der Vergangenheit, der ENC mittlerweile den Dienst quittiert hat?
... nur wenn es ein griechischer ENC ist: bei den Statuspings laut
rufen und wenns an die Arbeit geht, kaputt sein!? (SCNR)

von Sylvia H. (sandy)


Lesenswert?

Tiramisu schrieb:
> Bitte einen Breakpoint in enc28j60WriteBuffer() vor sendSPI(*data++)
> data setzen, ALLE Bufferinhalte kontrollierend durchsteppen und dann
> schauen ob da alles uebertragen wird (d.h. ob dann genuegend
> haendische Verzoegerung war :-) um ein ordentliches UDP-Paket
> zu schicken.

danke für den Tip, nach ungefähr 1295847846 Mausklicks (weher 
Zeigefinger lässt grüßen..) habe ich entdeckt, dass das UDP Paket zwar 
ordendlich gepackt war, aber ich doch glatt vergessen hatte, im Ip 
Header die Versionsnummer und die Headerlänge zu setzten. Schande über 
mich.....

also:
in die Methode makeDatasendheader() noch ein
//set IP Version and length
  EthIpHeader[IP_P] = IP_V4_V | IP_HEADER_LENGTH_V;
rein.

Jetzt kommt das UDP Paket an, Wireshark meint zwar auf einmal, der 
Sourceport wäre 0 anstatt 1200, aber das bekomme ich auch noch raus.

Mit eurer Hilfe habe ich wieder Mut gefasst!
Danke,danke,danke

von eProfi (Gast)


Lesenswert?

Hättest meine enc28j60.lbr enc28j60centered.lbr verwenden können (nicht 
umsonst bereits 1000 Downloads):
Beitrag "Re: ENC28J60 Eagle Lib Library verbessert"

Der ist auch noch interessant:
Beitrag "I/O über Ethernet mit einem ENC28J60"

Du schaffst es!

von ... (Gast)


Lesenswert?

Tiramisu schrieb:
> ... nur wenn es ein griechischer ENC ist: bei den Statuspings laut
> rufen und wenns an die Arbeit geht, kaputt sein!? (SCNR)

LOL, der war gut :)

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.