[En-Nut-Discussion] NutUdpSendTo taking too long

José Vallet jose.vallet at hut.fi
Thu Oct 29 18:02:19 CET 2009


Hello all.

We have found one weird behaviour of NutUdpSendTo. Basically the problem 
is the following.

If we put our Ethernut3 (with NutOS 4.6.4) to send UDP packets in a 
network that does NOT have a computer with the IP that the UDP packets 
are sent to, after some time (about 15 minutes) the Ethernut gets into a 
state where every single execution of NutUdpSendTo takes about 500ms. We 
can also see that in this state the microcontroller spends most of the 
time idling, which suggests that there is a wait process somewhere. To 
my poor understanding, sending a UDP packet is something like simply 
dropping the packet into the network, not waiting for anything.

After this, if a computer with the target IP "appears" (in linux I 
configure an ip alias), the situation comes back normal immediately, 
where it takes usually in the order of milliseconds to execute NutUdpSendTo.

This situation seems to be reproducible. A simple while loop sending UPD 
packets and a bit of patience makes the issue to show up. We measure 
time by setting pins up and down and with an oscilloscope/logic 
analyser. The basic code that we use is the following

-----------------------
#define MY_MAC  "\x00\x06\x98\x30\x00\x35"
#define MY_IPADDR "192.168.0.100"
#define MY_IPMASK "255.255.255.0"

int main(void)
{
   u_long ip_addr = inet_addr(MY_IPADDR);
   u_long ip_mask = inet_addr(MY_IPMASK);
   u_char mac[] = MY_MAC;
   UDPSOCKET *sock=NULL;
   char buf;

   DEBUGPINS_INIT;

   /* Initialize the serial port */
   NutRegisterDevice(&DEV_UART0, 0, 0);
   freopen("uart0", "r+", stdout);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   printf("\n\nNut/OS %s\n", NutVersionString());

   /* Register the tracer and start the terminal */
   btn_terminal_init(stdout, "[udp]$");
   btn_terminal_register_cmd("trace",NutTraceTerminal);
   btn_terminal_run(BTN_TERMINAL_FORK, 0);

   /* Register Ethernet controller */
   NutRegisterDevice(&DEV_ETHER, 0, 0);
   NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
   sock = NutUdpCreateSocket(LOCAL_PORT);
   if (sock==0)
   {
     DEBUGPINS_SETHIGH(2); //Set the debug pin 2 up
   }
   ip_addr=inet_addr(REMOTE_IP);
   while (1)
   {
     DEBUGPINS_SETHIGH(0); //Set the debug pin 0 up
     if (NutUdpSendTo(sock, ip_addr, REMOTE_PORT, &buf, 1) == -1)
     {
       DEBUGPINS_SETHIGH(3);
       NutSleep(200);
       DEBUGPINS_SETLOW(3);
     }
     DEBUGPINS_SETLOW(0); //Set the debug pin 0 low
     buf++;
   }
}
-----------------------

where the DEBUGPINS_SETHIGH(X) is a macro to put the Xth pin of our 
debug connector to 1, and similar with the rest of macros. The pin 1 is 
used to indicate when the micro is in the idle thread, and thus cannot 
be seen in the code here, as it is in the NutOS sources. As you can see 
we are able to use the tracer also in Ethernut3 (thanks to the 
modifications of Ernst Stippl) through the btn-terminal for easily 
getting the traces. If required we can provide sample traces and 
pictures of the measurements with the scope. We can also provide all the 
files required to run this code.

Regards
José



More information about the En-Nut-Discussion mailing list