[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