Pages: [1] 2 3   Go Down
Author Topic: Ethernet UDP hang  (Read 11012 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,
I'm getting mad trying to solve a random hang with arduino mega and ethernet shield...
I tried with latest ethernet library, stop interrupts before any ethernet lib call.
Even tried with a watchdog, but when the arduino hangs the watch dog doesn't reboot. Sometimes is also imposible to upload anything and I need to remove power.

The incoming message rate is 10ms, and the loop never takes longer, it usually takes 7/8 ms

The code is more or less like this....
Any cue?

Thanks!
Code:
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <util.h>
#include <avr/wdt.h>
//
//Other declaration stuff
//
void setup() 
{ //--- Create an interrupt to update a multiplexed display
  //
  TIMSK2 &= ~(1<<TOIE2);
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  ASSR &= ~(1<<AS2);
  TIMSK2 &= ~(1<<OCIE2A);
  TCCR2B |= (1<<CS22)  | (1<<CS20);
  TCCR2B &= ~(1<<CS21);
  TCNT2 = 0; //tcnt2;
  TIMSK2 |= (1<<TOIE2); 
  //---
  Ethernet.begin(mac,ip);
  Udp.begin(localPort); 
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
}
//--------------------------------------------------
ISR(TIMER2_OVF_vect) {
  iCount++;
  if (iCount == 5) {
    LCD.update();
    iCount = 0;
  }
}
//--------------------------------------------------
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
//-----------------------------------------
void loop() 
{     
  _dataIn in;
  _dataOut out;
 
  cli(); 
  int packetSize = Udp.parsePacket();   //The packet sended is 1 byte long, but packetSize is usually 10,11 or 12 ???
  if (packetSize) {
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    if (Udp.remotePort() == remotePort) {   //Sometimes the remotePort is different... I not sure why.
      memcpy((byte *)&in, packetBuffer, sizeof(_dataIn));
      //Assign incoming value to local variable
      //Prepare the output struct
      Udp.beginPacket(remoteIp, remotePort);
      Udp.write((byte *)&out, sizeof(_dataOut));
      Udp.endPacket();
     }
  }
  sei();
  //
  //Do thing with the incoming values
  //
 }
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just looking at it ,
The code will not even compile  take a look at the memcpy line.
Why should people waste their time, if you cannot take the time to supply a valid test case?

HC


Logged

0
Offline Offline
Tesla Member
***
Karma: 145
Posts: 9675
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The code is more or less like this....

More or less most people will ignore those that won't post the actual code that is causing a problem.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I was trying to make things as simple as possible, that's why I removed all not ethernet related stuff.
Anyways... digging into the problem I realizes that it gets stuck in a loop inside sendUDP. I need to investigate in depth what's happening, but I supposed it can't send the package and never gets timeout.

Code:
int sendUDP(SOCKET s)
{
  W5100.execCmdSn(s, Sock_SEND);
  /* +2008.01 bj */
  while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
  {
    if (W5100.readSnIR(s) & SnIR::TIMEOUT)
    {
      /* +2008.01 [bj]: clear interrupt */
      W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
      return 0;
    }
  }

  /* +2008.01 bj */
  W5100.writeSnIR(s, SnIR::SEND_OK);
  /* Sent ok */
  return 1;
}
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 148
Posts: 6105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you tried applying this fix?
http://code.google.com/p/arduino/issues/detail?id=605

It affects any 16 bit register read from the w5100. It has been around long enough to pick up the nickname "the 605 bug".
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep, actually I'm using the latest git version of ethernet library that already have the patch.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 148
Posts: 6105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK. That takes that out of the picture.

Next, this:
Code:
   if (Udp.remotePort() == remotePort) {   //Sometimes the remotePort is different... I not sure why.
      memcpy((byte *)&in, packetBuffer, sizeof(_dataIn));
      //Assign incoming value to local variable
      //Prepare the output struct
      Udp.beginPacket(remoteIp, remotePort);
      Udp.write((byte *)&out, sizeof(_dataOut));
      Udp.endPacket();
     }

I presume this is the server end. Is that correct? Your "server" is responding to another device UDP request?

What type device is on the other end, sending the request?

The reason the remote port is different is most of the time is that the client will not normally use the destination port. All my clients use ports other than port 80 on the client end to make http requests.

What is the value assigned to remotePort in your code? Maybe you should be using the port sent by the requesting device to reply to the request.

edit: If your ethernet shield is exposed to the internet, it may not be your device making some of the requests. It could be a port scanner looking for open ports to exploit.
« Last Edit: February 09, 2012, 07:49:04 am by SurferTim » Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The remote machine is a windows machine that sends to arduino's port 8888, and is always one machine and always the same one, then the arduino reads the package, compose the answer and send it back to windows machine on port 8888.

_dataIn size is 1 byte, and I just check that "int packetSize = Udp.parsePacket();" not always return 1 byte
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 148
Posts: 6105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK. I see. Not sure I can help you with that.

But it might help if you could be more specific about this?
Quote
_dataIn size is 1 byte, and I just check that "int packetSize = Udp.parsePacket();" not always return 1 byte
How often is "not always"?
What does it return when it isn't 1 byte? 2? 9?

edit: I just saw the comment in the original code. Between 10 and 12. And never less than 9?

« Last Edit: February 09, 2012, 10:44:02 am by SurferTim » Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You almost hit!... 10
Here you see only 8888 port incoming packages because I filtered all others before "167" are different traces inside sendUDP


Code:
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 3
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 6
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 4
        Cycle time: 1
        Cycle time: 1
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 4
        Cycle time: 1
        Cycle time: 1
PacketSize: 10  Port: 8888      Cycle time: 5
        Cycle time: 1
        Cycle time: 1
        Cycle time: 1
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
        Cycle time: 1
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
        Cycle time: 1
PacketSize: 10  Port: 8888      Cycle time: 4
        Cycle time: 1
        Cycle time: 1
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
        Cycle time: 2
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 2
        Cycle time: 2
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
        Cycle time: 1
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 7
        Cycle time: 1
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 9
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 8
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 6
        Cycle time: 3
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 6
PacketSize: 1   Port: 8888      Power: 1      Write: Ok167END Cycle time: 6
        Cycle time: 3
PacketSize: 10  Port: 8888      Cycle time: 3
        Cycle time: 1
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 148
Posts: 6105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not sure where that output came from.

Have you tried the example code here?
http://arduino.cc/en/Reference/EthernetUDPAvailable

Does that serial output help?

I don't see a "Serial.begin(9600);" in the setup function tho. ??
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduino 1.0 UDP sample doesn't have the call to available, anyways, the available() call is embedded in parsePacket().
I will try in my next run.

There's a Serial.begin(115200)

Edit: It seems to solve the wrong packet size... now is always 1, except very seldom 0 sizes, like data arrives between parsePacket() and available() calls
        Let's see what happens after a few hours.....

Edit2: Nop... even the wrong packet size appears again.... I think my next step is to  allow only a few retries in the loop of death
          Maybe is some timing issue, the "print" fail rate is much more smaller than the no serial output version

Edit3: SnIR::TIMEOUT is always 8 when the problem happend, rx light in the ethernet shield is always blinking (http://db.tt/bgB1VQLK in the video 1 and 2 are stucked and 3 is running fine)
« Last Edit: February 09, 2012, 02:58:37 pm by motote » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Inside this loop....

 while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
  {
    if (W5100.readSnIR(s) & SnIR::TIMEOUT)
    {
   
can you dump SnIR

HC
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 19
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

HardCore, you mean dumping the result of W5100.readSnIR(s). no?
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 98
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Same thing.
I'm asking for the register to be dumped your asking for a function returning the register to be dumped.

 I wanted to see the bottom 2 bits of SnIR  whilst this was going on.

Because UDP does not require an 'ACK' there should be absolutely no reason it does not (SEND_OK), other than the external network cable is already busy/ no destination.


Logged

Pages: [1] 2 3   Go Up
Jump to: