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
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.
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
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.
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.
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.
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 ;)
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?
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.
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.
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.
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.
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.
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?
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.
@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 */ |
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.