Forum: Mikrocontroller und Digitale Elektronik lwIP UDP Pakete senden


von W. R. (wrichter)


Lesenswert?

Hallo, alle miteinander. Ich versuche, kontinuierlich Daten von meinem 
XMC4500 Relax Kit via UDP an meinen PC zu senden. Der Sendevorgang 
findet in der Interrupt-Service-Routine eines Timers statt. Ich benutze 
Dave V4 und die ETH_lwIP App. Ich brauche eure Hilfe, weil der 
Übertragungsprozess nicht funktioniert. Mein Quellcode:






#include <DAVE.h>      //Declarations from DAVE Code Generation 
(includes SFR declaration)


#define TRANSMIT_PORT_DESTINATION   (45175)
#define LOCAL_PORT_TRANSMIT     (45174)

int main(void)
{
  DAVE_Init();      // Initialization of DAVE Apps
  //Start the lwIP stack
  ETH_LWIP_STATUS_t init_status;
  init_status = ETH_LWIP_Init(&ETH_LWIP_0);

  while(1)
  {
       /*Function called below, checks for timeout of different protocol 
timers and
       executes relevant handler functions
       */
       sys_check_timeouts();
  }
}

void UserIRQHandler(void)
{

  ip_addr_t ip_computer;
  IP4_ADDR(&ip_computer,192,168,0,40);

    struct udp_pcb *pcb_tr;
    pcb_tr = udp_new();
    udp_bind(pcb_tr,IP4_ADDR_ANY,LOCAL_PORT_TRANSMIT);

    char msg1[]="testingUDPtransmit";

    struct pbuf *ppp;
    ppp = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg1),PBUF_RAM);
    memcpy (ppp->payload, msg1, sizeof(msg1));
    udp_sendto(pcb_tr,ppp,&ip_computer,TRANSMIT_PORT_DESTINATION);
    pbuf_free(ppp);

}

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

was funktioniert denn nicht?
Ein paar Punkte die mir auffallen ...
1.sollte man das nicht innerhalb einer ISR versenden
2.dein Socket solltest du am Ende schließen, oder besser noch in der 
Main nur 1 Mal anlegen und für alle Vorgänge nutzen
3.ein Bind brauchst du nur wenn du auch empfangen willst, und auch hier 
kannst du ein Bind auf einen Port nur 1x ausführen, ohne das Socket 
freizugeben wird jedes weitere Bind auf den selben Port zu einem Fehler 
führen

Sascha

von W. R. (wrichter)


Lesenswert?

Vielen Dank schonmal für die Antwort. Ein paar deiner Vorschläge habe 
ich jetzt berücksichtigt und die UDP Pakete werden bei jedem Aufruf der 
ISR versendet. Welche Möglichkeit besteht denn, abgesehen von einer ISR, 
Daten im Sekundentakt per UDP zu versenden?
Für weitere Anmerkungen und Verbesserungsvorschläge bin ich sehr 
dankbar, da ich zum ersten mal mit UDP arbeite. Mein aktueller, 
angepasster Quellcode:



#include <DAVE.h>      //Declarations from DAVE Code Generation 
(includes SFR declaration)


#define TRANSMIT_PORT_DESTINATION   (45175)

struct udp_pcb *pcb_tr;
char msg1[]="testingUDPtransmit";
struct pbuf *ppp;
ip_addr_t ip_computer;


int main(void)
{

  DAVE_Init();      // Initialization of DAVE Apps

  //Start the lwIP stack
  ETH_LWIP_STATUS_t init_status;
  init_status = ETH_LWIP_Init(&ETH_LWIP_0);

  pcb_tr = udp_new();
  IP4_ADDR(&ip_computer,192,168,0,40);

  while(1)
  {
       /*Function called below, checks for timeout of different protocol 
timers and
       executes relevant handler functions
       */
       sys_check_timeouts();
  }
}

void UserIRQHandler(void)
{

    ppp = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg1),PBUF_RAM);
    memcpy (ppp->payload, msg1, sizeof(msg1));
    udp_sendto(pcb_tr,ppp,&ip_computer,TRANSMIT_PORT_DESTINATION);
    pbuf_free(ppp);

}

von Sascha W. (sascha-w)


Lesenswert?

Wilhelm R. schrieb:
> Vielen Dank schonmal für die Antwort. Ein paar deiner Vorschläge habe
> ich jetzt berücksichtigt und die UDP Pakete werden bei jedem Aufruf der
> ISR versendet.
das sieht ja schon mal gut aus

> Welche Möglichkeit besteht denn, abgesehen von einer ISR,
> Daten im Sekundentakt per UDP zu versenden?
in dem du in der ISR nur ein Flag setzt und dieses in der Main-loop 
abfragst.
Es geht ja primär darum die Bearbeitungsdauer der ISR auf das 
notwendigste zu begrenzen. Auch wenn das vielleicht jetzt bei einem 
Aufruf pro Sekunde kein Problem zu sein scheint, so kann das je nach 
Architektur des Controllers in Verbindung mit anderen zeitkritischen 
ISRs zu Problemen führen.
Beim AVR z.B. unterbrechen sich ISRs (wenn man es nicht erzwingt) nicht 
gegenseitig. Wenn nun die eine ISR ein Mal pro Sekunde10ms dauert eine 
zweite jedoch jede Millisekunde einen Zähler erhöhen soll "verliert" 
diese wenigstens 9 Aufrufe pro Sekunde.

> Für weitere Anmerkungen und Verbesserungsvorschläge bin ich sehr
> dankbar, da ich zum ersten mal mit UDP arbeite.
Auch den Puffer brauchst du nur 1x mit der größt möglichen Länge der 
Nachricht anzulegen.

Das hat aber alles nichts speziell mit dem versenden von UDP-Paketen zu 
tun.

Sascha

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Wilhelm R. schrieb:
> Welche Möglichkeit besteht denn, abgesehen von einer ISR,
> Daten im Sekundentakt per UDP zu versenden?

Arbeitest Du mit einem RTOS? Die übliche Vorgehensweise dort ist, eine 
Sendetask suspendiert zu halten und periodisch aufzuwecken (Stichtwort 
Signal oder Event, oft durch Semaphoren realisiert). Der Timer ISR setzt 
das Signal, womit das RTOS die Task aufweckt.

Eine andere sehr typische (ähnliche, aber nicht identische) 
Implementationsweise ist über eine Message Pump - dort würden nicht nur 
Signale des Timer ISR, sondern auch andere events abgearbeitet werden.

Man kann Netzwerksoftware ohne RTOS benutzen (lwip ist sogar explizit 
dafür vorgesehen), aber typischerweise macht ein System mehr als nur 
über das Netzwerk zu kommunizieren. In solchen Fällen macht ein RTOS 
sehr schnell Sinn.

Wie schon vorher gesagt ist das Aufrufen von Netzwerkfunktionen im ISR 
in aller Regel ein absolutes No-no - u.A. deshalb, weil Funktionen wie 
udp_sendto in der Regel so realisiert sind, dass sie in verschiedenen 
Szenarien den Aufrufer suspendieren können, und das ist in ISRs nicht 
möglich, Punkt.

von W. R. (wrichter)


Lesenswert?

Ruediger A. schrieb:

> Arbeitest Du mit einem RTOS? Die übliche Vorgehensweise dort ist, eine
> Sendetask suspendiert zu halten und periodisch aufzuwecken (Stichtwort
> Signal oder Event, oft durch Semaphoren realisiert). Der Timer ISR setzt
> das Signal, womit das RTOS die Task aufweckt.
>
Ich arbeitet nicht mit einem RTOS. Die Aufgabe meines Mikrocontrollers 
soll darin bestehen Messwerte mit Hilfe einer FFT zu analysieren und die 
berechneten Werte anschließend per UDP an MATLAB (R2016b) zu senden. 
MATLAB ist vorerst nur zur grafischen Auswertung dieser Daten zuständig.

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.