Forum: Mikrocontroller und Digitale Elektronik lwIP für STM32F4


von K. K. (caga001)


Lesenswert?

Hallo zusammen,

ich habe mir die Libary lwIP für die STM32F4 Familie von ST 
heruntergeladen und versucht das Beispiel Projekt udp_echoclient in 
meiner System Workbench for STM32 einzubinden.

Leider erhalte ich nachdem ersten build eine reihe von Fehlermeldungen, 
welche Sourcen der Libary betreffen.

Unter anderem wird keine Definition zu "MEMP_UDP_PCB" gefunden (und 
einigen weiteren Symbolen). Ich habe sämtliche Dateien manuell 
durchsucht und diese auch nicht gefunden. Nur ein Symbol 
"MEMP_NUM_UDP_PCB". Ist dieser Fehler bekannt?

Desweiteren habe ich viele Fehler mit "undefined reference to". Die 
Quelltext der Funktionen erreiche ich habe über STRG und Klick auf den 
Funktionsnamen. Beim weiteren Klicken bietet mir die IDE zwei 
Headerfiles zur Auswahl wo es den Prototypen gefunden hat.

Ich hoffe Ihr könnt mir weiterhelfen. Danke

von hust (Gast)


Lesenswert?

schau mal in die mem.h und memp.h

irgendwo da wird eine definition der ganzen MEMP_xxx  angelegt.
das problem habe ich auch das der compiler meckert , es aber dennoch 
kompiliert.

von caga001 (Gast)


Lesenswert?

Danke, habe ich jetzt auch nach langem Kopfzerbrechen herausgefunden.

Anscheinend führt diese Definition
1
/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */
2
typedef enum {
3
#define LWIP_MEMPOOL(name,num,size,desc)  MEMP_##name,
4
#include "lwip/memp_std.h"
5
  MEMP_MAX
6
} memp_t;

zu den Problemen.

Build führt zu Fehlermeldungen, aber Ausführen und Debuggen funktioniert 
wieder

von K. K. (caga001)


Lesenswert?

Ich habe folgenden Code aus einem Beispiel genommen und eine einfache 
Senderoutine hinzugefügt.
1
int main(void)
2
{
3
  /*!< At this stage the microcontroller clock setting is already configured to 
4
       168 MHz, this is done through SystemInit() function which is called from
5
       startup file (startup_stm32f4xx.s) before to branch to application main.
6
       To reconfigure the default setting of SystemInit() function, refer to
7
       system_stm32f4xx.c file
8
     */
9
10
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
11
12
#ifdef SERIAL_DEBUG
13
  DebugComPort_Init();
14
#endif
15
16
  /*Initialize LCD and Leds */
17
  LCD_LED_BUTTON_Init();
18
19
  /* Configure ethernet (GPIOs, clocks, MAC, DMA) */
20
  ETH_BSP_Config();
21
22
  /* Initilaize the LwIP stack */
23
  LwIP_Init();
24
25
  /* Infinite loop */
26
  while (1)
27
  {
28
29
    static uint8_t data[] = {1,2,3,4};
30
31
    volatile err_t status;
32
    volatile uint8_t free = 0;
33
34
    struct udp_pcb * udp;
35
36
    udp=  udp_new();
37
38
    struct ip_addr * ip_stm32 = NULL;
39
    IP4_ADDR(ip_stm32,192,168,0,10);
40
41
    struct ip_addr * ip_laptop = NULL;
42
    IP4_ADDR(ip_laptop,192,168,0,11);
43
44
    status = udp_bind(udp, ip_stm32, 1234 );
45
46
    status = udp_connect(udp, ip_laptop, 1234 );
47
48
    struct pbuf *p;
49
50
    p = pbuf_alloc( PBUF_TRANSPORT, 4, PBUF_RAM ) ;
51
    p -> payload = data;
52
    p->tot_len = 4;
53
54
    status = udp_send(udp, p);
55
56
    free = pbuf_free(p);
57
58
    status = udp_disconnect(udp);
59
60
    status = udp_remove(udp);
61
62
      LwIP_Periodic_Handle(LocalTime);
63
  }
64
}

Leider empfange ich die gesendeten Daten nicht. Erkennt einer einen 
Fehler und kann mir Tipps geben worauf ich zu achten habe?

Der Link - Interrupt funktioniert.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Was sagt denn der Debugoutpout vom lwip?
Schalt den mal ein, der ist sehr ergiebig ;)

Kommt denn überhaupt nen ARP vom lwip?
Der muss ja noch die MAC zur IP finden bevor das Paket auf Reisen gehen 
kann.

von K. K. (caga001)


Lesenswert?

Was meinst du mit Debugoutpout?

Der Hinweis auf das ARP ist gut. Der angesprochene Teilnehmer müsste ja 
darauf sofort reagieren. Werde ich prüfen.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Der lwip hat ne integrierte Debugausgabe.
Guck doch mal in den Headerfiles nach dem Debugout, den auf einen deiner 
UART umbiegen.
Dann in der config den Debug einschalten bis auf Info level runter.

Der lwip sagt dir dann von alleine wo der Schuh drückt ;)

von caga001 (Gast)


Lesenswert?

Danke für die Rückmeldung.
Muss ich dann eine serielle Verbindung zu meinem Pc über RS232 
herstellen?Oder wo bekomme ich die Meldungen angezeigt?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Naja, bevor man mit nem IP Stack anfängt sollte man schon wissen wie man 
die UART Ausgabe eines µC auf ein Terminal aufm PC angezeigt bekommt ;)

Ansonsten dieses Tutorial zum LWIP Einbau schon gefunden?
http://www.st.com/resource/en/application_note/dm00036052.pdf

Ist jetz zwar Atmel, aber Punkt6 ist was du lesen willst:
http://www.atmel.com/Images/Atmel-42233-Using-the-lwIP-Network-Stack_AP-Note_AT04055.pdf

Für jedes Modul, dass Debugausgabn machen soll muss das define in der 
config.h gesetzt werden.

Dein printf, welches auf deinem UART ausgibt, muss in der platform.h 
oder cc.h angelegt werden.
Dazu sollte dein STM32 Beispielcode eigentlich schon was mitgeliefert 
haben.

von caga001 (Gast)


Lesenswert?

Das habe ich auch hinbekommen.

Über ein einfaches UASART_send() empfange ich Daten auf meinem Terminal,
aber leider nicht vom TCP / IP Stack.


Das ST Tutorial hatte ich auch schon gefunden.

Beim Senden über UDP vom uC an den Laptop wird der ARP gesendet und der 
Laptop antwortet auch mit der MAC Adresse, allerdings werden dann keine 
Daten gesendet.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Der lwip erwartet auch nen printf und keine normale Stringausgabe.

Zur not eben mit nem snprintf in nen Stringbuffer schreiben und das mit 
deiner UASART_send() raussenden.

Wenn ein ARP kommt ist das schonmal gut.
Es kommt auch genau ein ARP?
Dann empfängt der lwip das auch, würde die Empfangsroutine nicht gehen, 
dann würde er nochmal ARPen (kann ja nen Paketverlust sein.)

zip mal dein lwip und häng den hier rein.

von K. K. (caga001)


Angehängte Dateien:

Lesenswert?

Ich hatte über USART_send() nur überprüft ob die Verbindung zwischen uC 
und PC funktioniert, da eine Ausgabe über printf nicht funktionierte.

Es kommt genau ein ARP und darauf eine Antwort mit der MAC Adresse.

Mein Projekt ist im Anhang. Es ist das Beispielprojekt von 
udp_echoclient von ST.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Da Blick ich jetz nich durch, der lwip Ordner ist völlig anders als wenn 
man ihn normal runterläd.

Da musste wohl selber in deiner IDE gucken wo zB ein 
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void 
*)msg));
Im Endeffekt rauskommt.

Ühne Debugausgabe ist es erstmal nich möglich zu gucken wieso da nix 
passiert.

von Stefan (Gast)


Lesenswert?

Es wird das Raw/UDP Interface von LwIP verwendet das ohne RTOS auskommt.
udp_send() wird zunächst versuchen die MAC Adresse zu dem Rechner mit 
der angegebenen IPv4 Adresse zu finden. Die hat er aber nicht. Also wird 
ein ARP Request versendet um diese MAC Adresse anzufordern. Mehr 
passiert nicht. udp_send() kehrt danach zum Aufrufer zurück. Und dort 
werden sofort udp_disconnect() + udp_remove() aufgerufen.

Wie könnte so jemals das eigentliche UDP Paket gesendet werden?

von K. K. (caga001)


Lesenswert?

Danke für den Hinweis.
Auf Ethernet-Ebene wird doch erst geprüft ob die MAC Adresse des Ziels 
vorhanden ist. Wenn nicht wird versucht diese über ARP vom Empfänger zu 
bekommen.Ich bin davon ausgegangen das anschließend das Paket auch 
versendet wird.

Müsste ich dann udp_send() erneut, nachdem die MAC-Adresse ermittelt 
wurde, aufrufen?

In dem Beispiel von st wird nach drücken eines Buttons folgende Funktion 
zum Senden aufgerufen
1
void udp_echoclient_connect(void)
2
{
3
  struct udp_pcb *upcb;
4
  struct pbuf *p;
5
  struct ip_addr DestIPaddr;
6
  err_t err;
7
       
8
  /* Create a new UDP control block  */
9
  upcb = udp_new();
10
  
11
  if (upcb!=NULL)
12
  {
13
    /*assign destination IP address */
14
    IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
15
  
16
    /* configure destination IP address and port */
17
    err= udp_connect(upcb, &DestIPaddr, UDP_SERVER_PORT);
18
    
19
    if (err == ERR_OK)
20
    {
21
      /* Set a receive callback for the upcb */
22
      udp_recv(upcb, udp_receive_callback, NULL);
23
      
24
      sprintf((char*)data, "sending udp client message %d", (int*)message_count);
25
  
26
      /* allocate pbuf from pool*/
27
      p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
28
      
29
      if (p != NULL)
30
      {
31
        /* copy data to pbuf */
32
        pbuf_take(p, (char*)data, strlen((char*)data));
33
          
34
        /* send udp data */
35
        udp_send(upcb, p); 
36
        
37
        /* free pbuf */
38
        pbuf_free(p);
39
      }
40
      else
41
      {
42
        /* free the UDP connection, so we can accept new clients */
43
        udp_remove(upcb);
44
        #ifdef SERIAL_DEBUG
45
        printf("\n\r can not allocate pbuf ");
46
        #endif
47
      }
48
    }
49
    else
50
    {
51
      /* free the UDP connection, so we can accept new clients */
52
      udp_remove(upcb);
53
      #ifdef SERIAL_DEBUG
54
       printf("\n\r can not connect udp pcb");
55
      #endif
56
    }
57
  }
58
  else
59
  {
60
    #ifdef SERIAL_DEBUG
61
     printf("\n\r can not create udp pcb");
62
    #endif
63
  } 
64
}

Dort wird nachdem senden nur der Buffer wieder freigegeben. Aber auch 
hier wird nachdem ARP keine Daten gesendet.
Bei erneutem Aufruf der Funktion wird laut Wireshark ein ECHO gesendet 
(ICMP?). Auf dieses aber keine Antwort kommt.

von K. K. (caga001)


Angehängte Dateien:

Lesenswert?

Im Anhang der Wireshark-Mitschnitt

von K. K. (caga001)


Lesenswert?

@MW En

In der debug.h ist es definiert
1
#ifdef LWIP_DEBUG
2
/** print debug message only if debug message type is enabled...
3
 *  AND is of correct type AND is at least LWIP_DBG_LEVEL
4
 */
5
#define LWIP_PLATFORM_DIAG printf
6
#define LWIP_DEBUGF(debug, message) do { \
7
                               if ( \
8
                                   ((debug) & LWIP_DBG_ON) && \
9
                                   ((debug) & LWIP_DBG_TYPES_ON) && \
10
                                   ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \
11
                                 LWIP_PLATFORM_DIAG message; \
12
                                 if ((debug) & LWIP_DBG_HALT) { \
13
                                   while(1); \
14
                                 } \
15
                               } \
16
                             } while(0)
17
18
#else  /* LWIP_DEBUG */
19
#define LWIP_DEBUGF(debug, message) 
20
#endif /* LWIP_DEBUG */

von K. K. (caga001)


Lesenswert?

Der Wireshark Eintrag:
Mit ECHO 70 Request ist für die gesendeten Daten.

Ich hatte in meinem Empfangsprogramm den falschen Port ausgewählt. 
Deshalb habe ich dort nichts empfangen.

@ Stefan: Du hast natürlich recht. Mein Code im ersten Beispiel kann so 
nicht funktionieren.

: Bearbeitet durch User
von K. K. (caga001)


Lesenswert?

Gibt es eine Möglichkeit empfangene Daten über Ethernet über einen 
Interrupt Handler zu verarbeiten.

in den Beispiel ist immer nur ein Polling in der main() aufgeführt.
1
   /* check if any packet received */
2
             if (ETH_CheckFrameReceived())
3
              {
4
                /* process received ethernet packet */
5
                LwIP_Pkt_Handle();
6
              }

Wie bekomme ich Zugriff auf die empfangenen Nutzdaten in meiner 
Applikation?

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.