Forum: Mikrocontroller und Digitale Elektronik AVR: ENC28J60 Ethernet Multicast


von Kai (kai_tl91)


Lesenswert?

Hallo, ich arbeite schon länger mit dem enc28j60 Ethernetchip. Soweit 
problemlos. Nun möchte ich Multicast Pakete empfangen. Leider 
funktioniert das nicht. Es werden nur Broadcast oder Unicast Pakete 
empfangen.

Zur Auswertung schicke ich die Daten direkt nach dem Empfang per UART 
raus.

Den Paketfilter habe ich bereits auf Multicast gesetzt bzw. auch 
komplett gelöscht. Keine Abweichung.

Paket abholen:
1
unsigned int enc_receive_packet( unsigned int bufsize, unsigned char *buf )
2
  {
3
    unsigned char rxheader[6];
4
    unsigned int len, status;
5
    unsigned char u;
6
7
    // check rx packet counter
8
    u = enc_read_reg( ENC_REG_EPKTCNT );
9
    ENC_DEBUG("enc_receive: EPKTCNT=%i\n", (int) u);
10
    if( u == 0 ) {
11
      // packetcounter is 0, there is nothing to receive, go back
12
      return 0;
13
    }
14
15
    //set read pointer to next packet
16
    enc_write_reg( ENC_REG_ERDPTL, LO8(enc_next_packet_ptr) );
17
    enc_write_reg( ENC_REG_ERDPTH, HI8(enc_next_packet_ptr) );
18
19
    // read enc rx packet header
20
    enc_read_buf( rxheader, sizeof(rxheader) );
21
    enc_next_packet_ptr  =             rxheader[0];
22
    enc_next_packet_ptr |= ((unsigned)(rxheader[1])) << 8;
23
    len                  =             rxheader[2];
24
    len                 |= ((unsigned)(rxheader[3])) << 8;
25
    status               =             rxheader[4];
26
    status              |= ((unsigned)(rxheader[5])) << 8;
27
        
28
        print("IN_STATUS: %4x ", status);
29
        if ((status & 0x0010)) print("| CRC-ERROR ");
30
        if ((status & 0x0020)) print("| LEN-CHECK-ERROR ");
31
        if ((status & 0x0040)) print("| LENGHT Out RANGE ");
32
        if ((status & 0x0080)) print("| RX OK ");
33
        if ((status & 0x0100)) print("| RX MC ");
34
        if ((status & 0x0200)) print("| RX BC" );
35
        if ((status & 0x0800)) print("| RecControlFrame ");
36
        if ((status & 0x2000)) print("| UNKNOWN-OPCODE ");
37
        if ((status & 0x4000)) print("| DECTECT-VLAN ");
38
        print("\r\n");
39
        
40
    // added by Sjors: reset the ENC when needed
41
    // If the receive OK bit is not 1 or the zero bit is not zero, or the packet is larger then the buffer, reset the enc chip and SPI
42
    if ((!(status & (1<<7))) || (status & 0x8000) || (len > bufsize))
43
    {
44
      enc_init();
45
    }
46
    //ENC_DEBUG("enc_receive: status=%4x\n", (unsigned) status);
47
48
    // skip the checksum (4 bytes) at the end of the buffer
49
    len -= 4;
50
51
    // if the application buffer is to small, we just truncate
52
    if( len > bufsize ) len = bufsize;
53
54
    // now read the packet data into buffer
55
    enc_read_buf( buf, len );
56
57
    // adjust the ERXRDPT pointer (= free this packet in rx buffer)
58
    if(    enc_next_packet_ptr-1 > ENC_RX_BUFFER_END
59
    || enc_next_packet_ptr-1 < ENC_RX_BUFFER_START ) {
60
      enc_write_reg( ENC_REG_ERXRDPTL, LO8(ENC_RX_BUFFER_END) );
61
      enc_write_reg( ENC_REG_ERXRDPTH, HI8(ENC_RX_BUFFER_END) );
62
      } else {
63
      enc_write_reg( ENC_REG_ERXRDPTL, LO8(enc_next_packet_ptr-1) );
64
      enc_write_reg( ENC_REG_ERXRDPTH, HI8(enc_next_packet_ptr-1) );
65
    }
66
67
    // trigger a decrement of the rx packet counter
68
    // this will clear PKTIF if EPKTCNT reaches 0
69
    enc_setbits_reg( ENC_REG_ECON2, (1<<ENC_BIT_PKTDEC) );
70
71
    // return number of bytes written to the buffer
72
    ENC_DEBUG("enc_receive: %i bytes\n", len);
73
    return len;
74
  }

Filterregister:
enc_setbits_reg( ENC_REG_ERXFCON, 0);

Hab ich etwas übersehen? Muss irgendwo ein Bit im NIC noch gesetzt 
werden oder hat der Chip ein Problem, dass IGMP z.B. < 61 Bytes ist?

Ich freue mich über jeden Tipp. DANKE!

: Bearbeitet durch User
von Kai (kai_tl91)


Lesenswert?

-Hochschieb- 😉 Jemand eine Idee 💡 ?

von Uwe (uhi)


Lesenswert?

Leider nur eine Idee in der anderen Richtung: ist sicher, dass die 
Pakete überhaupt auf der Leitung sind? Hatte mir für solche kniffligen 
Fälle extra einen uralten Hub (nicht Switch) organisiert, der den 
kompletten Traffic auf alle Ports legt, so dass man mit Wireshark sieht 
was da tatsächlich läuft, wenn zwei nicht so richtig miteinander reden 
wollen.

: Bearbeitet durch User
von Kai (kai_tl91)


Lesenswert?

Danke für den Tipp. Ich habe das umfänglich geprüft. Multicast wird 
generell erstmal per Broadcast gesendet und das habe ich auch nochmal 
mit Port Spiegelung überprüft. Die Pakete gehen definitiv raus. Auch 
Multicast Paket vom ENC28J60 kommen am PC an. Es betrifft nur den 
Empfang!

von Chris K. (kathe)


Lesenswert?

Kai schrieb:
> -Hochschieb- 😉 Jemand eine Idee 💡 ?

Managebare L2/3 Switches im Einsatz ?
Schau dir mal Paketbeschleunigung  in der Fritzbox an.
Vermeide den Weg über die Fritzbox.

von Kai (kai_tl91)


Lesenswert?

Chris K. schrieb:
> Kai schrieb:
>> -Hochschieb- 😉 Jemand eine Idee 💡 ?
>
> Managebare L2/3 Switches im Einsatz ?
> Schau dir mal Paketbeschleunigung  in der Fritzbox an.
> Vermeide den Weg über die Fritzbox.

Keine Sorge, AVR und PC stecken am selben Switch im selben Netz. Wie 
gesagt der Trafic kommt auch auf den Port.

: Bearbeitet durch User
von Uwe (uhi)


Lesenswert?

Ich würde das Problem eingrenzen, indem ich einen funktionierenden Frame 
nehme, und dann Bit für Bit ändere, schicke, schaue, bis er plötzlich 
nicht mehr ankommt. Mehrfach, um festzustellen, ob immer das gleiche Bit 
den Ausschlag gibt, oder Zufallseffekte im Spiel sind. Kann mir 
eigentlich nur vorstellen, dass ein Filter auf die MAC-Adresse noch 
irgendwo übrig geblieben ist beim Umbauen.

von Mario M. (thelonging)


Lesenswert?

Kai schrieb:
> Multicast wird generell erstmal per Broadcast gesendet

Genau genommen ist die Broadcast-Adresse ff-ff-ff-ff-ff-ff eine 
spezielle Multicast-Adresse. Mit welcher MAC-Adresse werden die Pakete 
vom PC gesendet? Bessere Switche geben Multicast erst weiter, nachdem 
die Empfänger sich per IGMP dafür angemeldet haben. Verbinde PC und 
ENC28J60 doch mal direkt per Crossover-Kabel.

Kai schrieb:
> Filterregister:
> enc_setbits_reg( ENC_REG_ERXFCON, 0);

Damit aktiviert man den Promiscuous-Mode, damit müssen alle Pakete 
empfangen werden.

von Dieter S. (ds1)


Lesenswert?

Was macht denn die Funktion enc_setbits_reg() genau, setzt/löscht sie 
einzelne Bits oder schreibt sie das Byte ins Register?

Ich hatte vor einer Weile einen ENC28J60 mit einem STM32 verwendet und 
da hat der Multicastempfang soweit ich mich erinnere funktioniert. Bei 
mir war nur das "CRCEN" Bit im ERXFCON Register gesetzt.

Eventuell auch mal das ERXFCON Register zurücklesen und schauen was dort 
tatsächlich steht.

von Dieter S. (ds1)


Lesenswert?

Ich habe noch mal kurz das Code-Fragment des TO angeschaut, es gibt dort 
enc_write_reg() und enc_setbits_reg(). Dann wird wohl enc_setbits_reg() 
einzelne Bits im Register setzen und der Aufruf 
"enc_setbits_reg(ENC_REG_ERXFCON, 0)" müsste dann vermutlich 
"enc_write_reg(ENC_REG_ERXFCON, 0)" sein damit es das gewünschte macht.

von Mario M. (thelonging)


Lesenswert?

Dieter S. schrieb:
> müsste dann vermutlich "enc_write_reg(ENC_REG_ERXFCON, 0)" sein damit es
> das gewünschte macht.

Stimmt. Mir war entgangen, dass da nur das Broadcast-Bit gesetzt wird. 
Sonst würde ja nur Broadcast erlaubt. Für Multicast müsste Bit 1 (MCEN) 
gesetzt sein.

von Kai (kai_tl91)


Lesenswert?

Uwe schrieb:
> Ich würde das Problem eingrenzen, indem ich einen funktionierenden Frame
> nehme, und dann Bit für Bit ändere, schicke, schaue, bis er plötzlich
> nicht mehr ankommt. Mehrfach, um festzustellen, ob immer das gleiche Bit
> den Ausschlag gibt, oder Zufallseffekte im Spiel sind. Kann mir
> eigentlich nur vorstellen, dass ein Filter auf die MAC-Adresse noch
> irgendwo übrig geblieben ist beim Umbauen.

Das wäre eine aufwendige aber sehr detaillierte Idee um das Problem 
einzugrenzen. Danke für den Tipp. Werde ich vermutlich so machen müssen.

Mario M. schrieb:
> Genau genommen ist die Broadcast-Adresse ff-ff-ff-ff-ff-ff eine
> spezielle Multicast-Adresse. Mit welcher MAC-Adresse werden die Pakete
> vom PC gesendet? Bessere Switche geben Multicast erst weiter, nachdem
> die Empfänger sich per IGMP dafür angemeldet haben.

Korrekt, wenn Multicast Snooping deaktiviert ist sendet der Switch es 
als Broadcast, also auf allen Ports. Der AVR meldet sich über den NIC 
bereits für die passende Gruppe an. Zudem habe ich kontrolliert, dass 
die Paket auch wirklich aus dem Port kommen. Das ist zumindest 
sichergestellt. Aktuell bezieht sich das Problem nur auf dem Empfang der 
MC Paket zwischen Switchport Ausgang und AVR SPI Eingang. Also auf den 
ENC28J60. Da liegt im Moment das Problem.

Dieter S. schrieb:
> Was macht denn die Funktion enc_setbits_reg() genau, setzt/löscht sie
> einzelne Bits oder schreibt sie das Byte ins Register?

Tatsächlich ist es die falsche Funktion, es muss heißen: 
enc_write_reg(); //damit wird das komplette Byte geschrieben. Werde ich 
testen.

Mario M. schrieb:
> Stimmt. Mir war entgangen, dass da nur das Broadcast-Bit gesetzt wird.
> Sonst würde ja nur Broadcast erlaubt. Für Multicast müsste Bit 1 (MCEN)
> gesetzt sein.

Nicht ganz korrekt: Wird der Filter aktiviert, müssen mehrere Bits 
gesetzt werden, oder halt keine, wenn der Filter aus sein soll.

Danke erstmal für die ganzen Tipps. Ich schau mir das jetzt im Detail 
nochmal an.

von Kai (kai_tl91)


Lesenswert?

Der Teufel steck meist im Detail:
Das Problem lag tatsächlich am Filter: Beim Einsetzen der Funktion, habe 
ich write BIT mit write BYTE vertauscht. Kleiner Unterschied, große 
Wirkung! Das war der entscheidene Tipp!

Dann bleibt nur zu hoffen, dass Anderen dieses Thread nutzt, wenn sie 
ein ähnliches Problem mit dem Empfang von Paketen haben.

VIELEN DANK!

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.