Forum: Mikrocontroller und Digitale Elektronik STM32-E407 Ethernet / UDP


von Markus M. (mmax)


Lesenswert?

Hi,

Nachdem ich mein Board [1] soweit am laufen habe, möchte ich als 
nächsten Schritt Ethernet nutzen. Hat schon mal jemand mit diesem Board 
einen TCP/IP Stack, ohne Betriebssystem also bare metal, zum laufen 
gebracht?

Ich brauch eigentlich nur via UDP Pakete empfangen und senden, soll ich 
da eher den uIP oder lwIP TCP/IP Stack näher ins Auge fassen?

Es gibt Beispielcode von Olimex selbst [2] und von ST [3] zum 
downloaden, muss mir das aber erst genauer anschauen.

[1] https://www.olimex.com/Products/ARM/ST/STM32-E407
[2] 
https://www.olimex.com/Products/ARM/ST/STM32-E407/resources/STM32-E_revB1_demo.zip
[3] 
http://www.st.com/web/en/catalog/tools/FM147/CL1794/SC961/SS1743/PF257906

lG,
Max

von Markus M. (mmax)


Lesenswert?

Ich hab jetzt den uIP Stack erfolgreich implementiert, senden und 
empfangen von UDP Telegrammen funktioniert also schon mal.

Weiss jemand ob man ICMP Ping replies selbst generieren muss oder sollte 
das uIP selbst machen? Hab diesbezüglich auch nichts in der uip-conf.h 
gefunden.

lG,
Max

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Markus Manninger schrieb:
> Weiss jemand ob man ICMP Ping replies selbst generieren muss oder sollte
> das uIP selbst machen?

Es gibt kein ICMP Ping. Die entsprechende Netzwerknachricht heißt ICMP 
ECHO bzw. die Antwort darauf ICMP ECHO REPLY. Beides existiert auch in 
uIP. ECHO (REPLY) ist übrigens der einzige ICMP-basierte Dienst in uIP. 
Andere ICMP-Nachrichten werden nicht unterstützt.

Das Anwendungsprogramm, mit dem man ICMP ECHO-Anfragen versenden und 
ICMP ECHO REPLY empfangen kann, heißt auf den meisten Plattformen 
"ping".

: Bearbeitet durch User
von Markus M. (mmax)


Lesenswert?

Jawohl!

Die Frage ist nur wie ich den Stack dazu bringe das ICMP ECHO REPLY 
Telegramm zu verschicken?

von Markus M. (mmax)


Lesenswert?

Naja, das senden funktioniert doch noch nicht so zuverlässig ... die 
Telegramme werden sporadisch verschickt.

Was muss man ausser "uip_send(ptr, len)" noch machen, damit die Daten 
via UDP raus gehen?

Ich frag mich eigentlich wo man die Destination (Host & Port) angeben 
muss, mit:
1
    uip_ipaddr(ipaddr, 192, 168, 0, 1);
2
    uip_setdraddr(ipaddr);
3
4
    udp_conn = uip_udp_new(&ipaddr, HTONS(5555));
5
6
    if (udp_conn != NULL) {
7
        uip_udp_bind(udp_conn, HTONS(5555));
8
        uip_udp_periodic_conn(udp_conn);
9
    }

wartet man ja nur auf eingehende Telegramme von dem Host.

Danke,
Max

von Markus M. (mmax)


Lesenswert?

Kann mir jemand weiterhelfen ... bekomms einfach nicht hin einfach ein 
paar Zeichen via UDP zu verschicken. Ich hab den uIP Stack noch nicht 
ganz durchblickt ... uip_send() alleine reicht nicht, aber was muss ich 
noch machen damit das komplette UDP Paket via Ethernet verschickt wird?

Muss ich das in der UIP_APPCALL machen?

Danke,
Max

von Markus M. (mmax)


Lesenswert?

Ausgehend von diesem [1] code, hab ich folgendes gemacht.

Nachdem das Ethernet Interface initialisiert wurde:
1
    clock_init(2);
2
3
    timer_set(&periodic_timer, CLOCK_SECOND / 2);
4
    timer_set(&arp_timer, CLOCK_SECOND * 10);
5
6
    tapdev_init();
7
    uip_init();
8
9
    uip_ipaddr(ipaddr, 192, 168, 0, 2);
10
    uip_sethostaddr(ipaddr);
11
12
    uip_ipaddr(ipaddr, 255, 255, 255, 0);
13
    uip_setnetmask(ipaddr);
14
15
    uip_ipaddr(ipaddr, 192, 168, 0, 1);
16
    uip_setdraddr(ipaddr);
17
18
    udp_conn = uip_udp_new(&ipaddr, HTONS(5555));
19
20
    if (udp_conn != NULL) {
21
        uip_udp_bind(udp_conn, HTONS(5555));
22
        uip_udp_periodic_conn(udp_conn);
23
    }

Will ich jetzt ein Telegramm verschicken, mach ich folgendes:
1
    uip_ipaddr(ipaddr, 192, 168, 0, 1);
2
    
3
    char data[] = "Test\r\n";
4
    uint8_t len = strlen(data);
5
    
6
    uip_ipaddr_copy(&udp_conn->ripaddr, ipaddr);
7
   
8
    uip_send(data,len);
9
    uip_process(UIP_UDP_SEND_CONN);
10
    tapdev_send( uip_appdata, len);

Doch leider bekomm ich immer leere Pakete ... niemand eine Idee? sitz 
schon den ganzen Tag davor, ohne Erfolg.

[1] 
https://github.com/contiki-os/contiki/blob/master/core/net/uip-udp-packet.c

lG,
Max

von Markus M. (mmax)


Lesenswert?

Keiner eine Ahnung was das Problem sein könnte?

Wenn ich Daten via UDP versenden will, muss ich, denke ich zumindest, 
folgende zwei uIP-Stackfunktionen aufrufen:

1
uip_send(data,len);
2
uip_process(UIP_UDP_SEND_CONN);

Doch wo sind die Daten, inkl. TCP/IP Header, die ich dann übers 
interface rausschicken muss?

Mach ich danach ein tapdev_send(uip_appdata,uip_len), fehlt mir der 
Header und ich sehe im wireshark ein ungültiges Paket das direkt mit 
"Test", also dem UDP content, beginnt.

Gibts denn wirklich niemanden hier der ein bisserl mit uIP Stack zu tun 
hatte?

: Bearbeitet durch User
von Uwe B. (derexponent)


Lesenswert?

Markus Manninger schrieb:
> Gibts denn wirklich niemanden hier der ein bisserl mit uIP Stack zu tun
> hatte?

ich leider nicht...kann dir also nicht direkt helfen

aber falls du nicht weiterkommst und von uIP auf lwIP wechseln willst, 
da gibts von STM fertige Beispiele dafür

hier sind welche von mir für einen UDP-Server :

http://mikrocontroller.bplaced.net/wordpress/?page_id=1756

und einen HTTP-Server :

http://mikrocontroller.bplaced.net/wordpress/?page_id=1529

vlt kommst du damit schneller klar

UB

von Markus M. (mmax)


Lesenswert?

Ah, danke. Bin eh schon mehrmals über deine Seite gestolpert ... finde 
sie sehr gut mit vielen praktischen Beispielen. Hab mir auch schon 
einiges davon abgeschaut!

Ich wollte eigentlich beim uIP bleiben, da ich nur UDP Telegramme 
empfangen und senden muss, und das ganz ohne Zeitstress und da sollte 
der kleinere uIP schon genügen ... wenn ich aber überhaupt net 
weiterkomm werd ich mir wohl den lwIP anschaun.

Aber ich kann mir nicht vorstellen dass da bei mir noch so viel fehlt. 
Ich denke ich greife beim verschicken einfach nur auf einen falschen 
Buffer zu, oder so. Und ich weiss nicht ob ich von jeder Stelle in 
meinem Source aus was verschicken kann oder ob ich das immer in der 
APPCALL machen kann. Laut den Beispielen im Netz [1] schauts irgendwie 
so aus:

1
  uip_len = ethernet_devicedrver_poll();
2
  if(uip_len > 0) {
3
    if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
4
      uip_arp_ipin();
5
      uip_input();
6
      if(uip_len > 0) {
7
        uip_arp_out();
8
        ethernet_devicedriver_send();
9
      }
10
    } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
11
      uip_arp_arpin();
12
      if(uip_len > 0) {
13
        ethernet_devicedriver_send();
14
      }
15
    }

[1] 
http://www-users.cs.york.ac.uk/~pcc/MCP/examples/html/group__uipdevfunc.html

von avr3 (Gast)


Lesenswert?

Eine Alternative ist eventuelle der UDP-Stack den es bei freertos.org 
gibt. Hat damit schon jemand gearbeitet?

von Markus M. (mmax)


Lesenswert?

Naja, ich will/brauch eigentlich kein Betriebssystem.

Bin grad dabei den lwip in mein projekt einzubauen und steh jetzt beim 
linken noch vor einer "undefined reference". Ich brauch ein 
Implementierung der Funktion sys_now(), die vom lwip 1.4.1 benötigt 
wird.

Leider steht irgendswo, was die funktion lieferen soll, aber ich schätze 
mal die aktuelle Zeit ... aber in welchem Format? Hat vielleicht jemand 
diese Funktion auf einem STM32F407 umgesetzt?

Danke,
Max

von Uwe B. (derexponent)


Lesenswert?

bei mir ist im File "opt.h" der Define dazu auf "0"
1
#define LWIP_TCP_TIMESTAMPS             0

damit wird "sys_now()" nicht eingebunden

Gruss Uwe

von Markus M. (mmax)


Lesenswert?

Ich hab jetzt den SysTick_Handler() dafür verwendet und die Funktion 
sys_now() liefert dann die ms seit startup.

von Markus M. (mmax)


Lesenswert?

So, wieder mal ein paar Fragen.

Ich bin jetzt dabei vom uIP auf den lwIP TCP/IP Stack umzustellen. Für 
lwIP findet man ja auch Beispielcode von ST selbst [1].

Da ich aber einen anderen Ethernet PHY (ks8721bl) hab, muss ich 
Änderungen am Source vornehmen. Ich denke mal dass davon die Dateien 
ethernetif.c (im Verzeichnis 
STM32F4x7_ETH_LwIP_V1.1.0/Utilities/Third_Party/lwip-1.4.1/port/STM32F4x 
7/Standalone)  und stm32f4x7_eth_bsp.c (im Verzeichnis 
STM32F4x7_ETH_LwIP_V1.1.0/Project/Standalone/udp_echo_server/src/) 
betroffen sind.

Ich gehe mal davon aus dass die Anschlüsse an den STM32F407 die selben 
sind, bin sie nur kurz überflogen und da schauts gut aus ... eh klar, 
der Ethernetcontroller befindet sich ja am Chip ... oder kanns da 
drotzdem Unterschiede geben?

Leider finde ich keine lwIP Beispiel für diesen PHY im Netz.

[1] http://www.st.com/web/en/catalog/tools/PF257906
[2] 
https://www.olimex.com/Products/ARM/ST/STM32-E407/resources/STM32-E_revB1_demo.zip

von katastrophenheinz (Gast)


Lesenswert?

Hi,

eigentlich sind die einzigen Änderungen in stm32f4x7_eth_bsp.c.
Hier musst du ggf den GPIO-Pin, über den er PHY seinen Interrupt 
anzeigt, anpassen ( das passiert in Eth_Link_EXTIConfig ), dann die 
Anpassungen an die "vendor specific" Register des PHY vornehmen, damit 
der über Interrupt LinkUp und LinkDown anzeigen kann ( das erfolgt in 
Eth_Link_PHYITConfig ).
Die entsprechenden Register findest du im Datenblatt deines PHY. Der 
originale code in ...bsp.c ist ja für den DP83848 geschrieben. Ich hab 
mir das Datenblatt für den und für meinen PHY nebeneinandergelegt und 
dann stur nach Schema f den entsprechenden Code geändert.

Dann musst du noch die EXTI-Interrupt-Routine so anpassen, daß du LinkUp 
und LinkDown erkennst und aus der Interrupt-Routine entweder 
netif_set_link_down(&gnetif) oder netif_set_link_up(&gnetif) aufrufen.
Entsprechender Code findet sich als "Eth_Link_ITHandler" in ...bsp.c, 
aber nicht in Form eines IRQ-Handlers.

Dann habe ich noch in irgendeinem Olimex-Beispielcode dieses Fragment 
zur dynamischen Ermittlung der Adresse des PHY gefunden, den hab ich 
auch eingebaut.
1
static int ETH_Find_Phy_Address(uint16_t *addr)
2
{
3
  unsigned int PhyAddr;
4
    union {
5
      uint32_t    HI_LO;
6
      struct
7
      {
8
        uint16_t  LO;
9
        uint16_t  HI;
10
      };
11
    } PHYID;
12
  for(*addr = 0; 32 > *addr; (*addr)++)
13
  { 
14
      // datasheet for the SMSC LAN8710A 
15
      // page 54/55 --> PHY Identifier 1 and 2
16
      PHYID.HI = ETH_ReadPHYRegister(*addr,2);  // 0x0007
17
      PHYID.LO = ETH_ReadPHYRegister(*addr,3) & 0xFFF0;  // 0xC0F0  , 4 LSB vary with silicon revision
18
      if (0x0007C0F0 == PHYID.HI_LO)
19
        break;
20
  }
21
   
22
  if(32 < *addr) printf_("Ethernet Phy Not Found\n\r");
23
  
24
25
  return (32 >= *addr);
26
}

Drei Abende Jugend forscht, aber jetzt rennt's fehlerfrei. Wenn du 
möchtest, kann ich dir meine stm32f4x7_eth_bsp.c zur Verfügung stellen, 
die ist jedoch angepasst für einen LAN8710A

Gruss, Heinz

von Markus M. (mmax)


Lesenswert?

Danke für die Antwort aber ich habs mittlerweile auch schon hinbekommen!

lG,
Max

von Mehmet K. (mkmk)


Lesenswert?

katastrophenheinz schrieb:
> ... kann ich dir meine stm32f4x7_eth_bsp.c zur Verfügung stellen,
> die ist jedoch angepasst für einen LAN8710A

Darf ich von diesem Angebot gebrauch machen?
Dank im voraus.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Anbei die Files.

lG,
Max

von Rainer B. (katastrophenheinz)


Lesenswert?

Mehmet Kendi schrieb:
> katastrophenheinz schrieb:
>> ... kann ich dir meine stm32f4x7_eth_bsp.c zur Verfügung stellen,
>> die ist jedoch angepasst für einen LAN8710A
>
> Darf ich von diesem Angebot gebrauch machen?
> Dank im voraus.

Brauchst du meine Datei noch oder bist du mit der von Markus rundum 
sorglos?

Gruss , Rainer

von Mehmet K. (mkmk)


Lesenswert?

Sorry für die verspaetete Antwort.
Erstmal herzlichen Dank an Markus! Schönes Weihnachtsgeschenk :)

@Rainer: ich schau' mir die Arbeit von Markus heute Abend mal an. Sollte 
es irgendwo harzen, werde ich auf Dein Angebot zurückkommen.

Mann bin ich froh, dass ich das Ganze nicht auf den LAN8710A anpassen 
muss \o\   \o/

: Bearbeitet durch User
von Mehmet K. (mkmk)


Lesenswert?

Du, Markus, ich hab' jetzt mal die Dateien etwas beschnuppert.
Da sehe ich aber was von KS8721, nichts aber von LAN8710A.
Sind diese PHYs identisch in ihrer Ansteuerung?

von Rainer B. (katastrophenheinz)


Lesenswert?

Mehmet Kendi schrieb:
> Sind diese PHYs identisch in ihrer Ansteuerung?
Schneller Blick in die beiden Datenblätter zeigt: Nein.
Sehen zwar ziemlich ähnlich aus, aber unterscheiden sich in kleinen, 
aber entscheidenden Details, z.B. Interrupt Control/Status Register

Gruss, Rainer

von Mehmet K. (mkmk)


Lesenswert?

Hmm, das war ja der User katastrophenheinz, der mit LAN8710A arbeitet.
Als ich die Files sah, kam mir gar nicht in den Sinn, den Absender zu 
kontrollieren.
Naja, dann werde ich nolens volens die Karbidlampe aufsetzen und in den 
Stollen herabsteigen müssen. Trozden herzlichen Dank für die 
Hilfsbereitschaft.

von Rainer B. (katastrophenheinz)


Lesenswert?

Wie oben bereits gesagt: Du kannst von mir die angepasste Version für 
einen
LAN8710A haben. Allerdings habe ich das nun schon für die Tasking 
Library von Rowley Crossworks erweitert. Den Teil müsstest du dann 
wieder rauswerfen.

Gruss, Rainer

von Mehmet K. (mkmk)


Lesenswert?

Ich dachte, auch Du haettest das Ganze auf den E407 mit dem KS8721 PHY 
angepasst.
Waere natürlich sehr nett von Dir, wenn Du mir Deine Arbeit zur 
Verfügung stellen würdest.
(Karbidlampe wieder ausgeblasen) :)

von Rainer B. (katastrophenheinz)


Angehängte Dateien:

Lesenswert?

Ok. Hier isses - aus dem laufenden Projekt rauskopiert. D.h. du wirst 
auf jeden Fall anpassen müssen.

Gruss, Rainer

von Mehmet K. (mkmk)


Lesenswert?

Vielen herzlichen Dank.

von Mehmet K. (mkmk)


Lesenswert?

Rainer, kannst Du mir bitte auch die stm32f4x7_eth_conf.h Datei zukommen 
lassen.
Zumindest nehme ich an, dass du die PHY Register dort definiert hast. Es 
geht um die Register PHY_MIFR, PHY_MCSR, ... PHY_MISR_LINK_INT_EN usw.

Dank im voraus.

von Rainer B. (katastrophenheinz)


Angehängte Dateien:

Lesenswert?

Na klar, sorry.
Die C-Datei habe ich auch noch dazu gepackt, weil die bei mir auch ein 
neueres Änderungsdatum aufweist, ich seh' aber auf den ersten Blick 
keine Änderungen von mir.

Viel Erfolg, Rainer

von Mehmet K. (mkmk)


Lesenswert?

Danke!
Hatte schon damit angefangen beide Datenblaetter vergleichend die 
entsprechenden defines zu erstellen.
Bua!
Hast mir schon 'ne heiden Last abgenommen!

von Rainer B. (katastrophenheinz)


Lesenswert?

;-) Das mit den Register-Mapping geht noch relativ fix.
Krude wird es erst, wenn du feststellst, daß der LAN...-PHY keinen 
Interrupt bei LinkUp auslösen kann. Dafür habe ich das "Autonegotiate 
Complete" als Interruptursache missbraucht, wie du vllt schon gesehen 
hast.
Kann man bestimmt auch besser lösen, aber tut auch so.

Gruss, Rainer

von Mehmet K. (mkmk)


Lesenswert?

Servus Rainer! Hat auf Anhieb geklappt. Nochmals 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.