[En-Nut-Discussion] fread() on serial port 0 problem

Kyle Rhodes kyle at ghbraille.com
Fri Nov 21 07:04:17 CET 2003


Hello all, 

I'm reposting this, because I'm not sure if it made it onto the list the
first time.  In case it was posted, I have added some more
information...  (sorry, this is pretty long winded)

In a Nut/OS 3.3.2 program one of the things I'm doing is reading from
serial port 0 using fread().  Occasionally, fread() returns < 0.  This
puzzles me, since shouldn't it block until the specified number of bytes
are available?  I don't see how an error condition could form with this
embedded hardware.  (Unless maybe a parity or framing error is generated
within the UART, is this checked for?)  I had big problems with this
issue using version 3.3.0, it always failed.  To fix the problem
(mostly) I upgraded to 3.3.2.  It works a lot of the time, maybe 85%,
but others it returns the error.  It seems I may have found a pattern in
failure.  The program reads in cycles, first data of arbitrary length is
sent out the serial port.  The controller on the other side does stuff
with the data and returns a packet 60 bytes long.  The Nut/OS controller
picks up this packet and sends more data depending on the status within
a status packet.  If this cycle continues as stated, it always works
fine.  Things start to fail if the packet contained a certain status
which required another packet to be read before more data is sent out
the serial port.  I guess I should also mention the Nut/OS controller is
also a TCP server, and that is where the data is coming from to send out
the serial port.  After the status packets are picked up from the serial
port, they are sent to the client via TCP.  What I'm picking up on the
other end is puzzling.  Like I said earlier, if the normal process of
send data, get data, send data, get data, is followed, everything works
fine.  I see the status packets on the client TCP side just fine.  Once
one of the packets is such that it needs to not send data in that order,
I see strange results.  On the client I get one packet which indicates
state A.  Then when the next packet is transmitted to the Nut/OS
controller via the serial port, I start to get strange results.
'Sometimes' fread returns as I stated above.  Other times, the
controller just disconnects the client and starts accepting connections
like nothing happened (it doesn't seem to reset after a crash, just act
as if it was complete with the job, and started accepting again in the
loop).  One interesting note is that if fread() returns an error, the
whole process I stated above that normally works, stops working
altogether.  fread() from that point on, even with a whole new
connection fails.  The only way to get it to work at all is to reset the
controller.  

After seeing the pattern explained above, I thought for sure the problem
was in my code.  But I've been over it a hundred times, and I don't see
any reason for it to fail.  As I mentioned the Nut/OS server sometimes
disconnects from the client.  This should never happen without it
sending a status packet back to the client.  I can't explain why that
doesn't happen since in my code it always writes a packet before it
disconnects, yet when this error occurs I don't always get the last
packet...

Here is how I'm opening the serial port and reading data from it:

  //Open serial port
  NutRegisterDevice(&devUart0, 0, 0);
  cd.rs232 = fopen("uart0", "r+b");

  tmp = DATA_UART_SPEED;                
  _ioctl(_fileno(cd.rs232), UART_SETSPEED, &tmp);

   tmp = 1;                     //Odd parity
   _ioctl(_fileno(cd.rs232), UART_SETPARITY, &tmp);

  NutSleep(500);

///////////////////////////////////////////////////////

size_t readFull(void *ptr, size_t size, FILE *fp)
{
  size_t retVal;
  size_t numRead = 0;
  unsigned char *cptr;

  cptr = (unsigned char *) ptr;

  while(numRead < size)
  {
    retVal = fread(&cptr[numRead], 1, size - numRead, fp);

    if(retVal < 0)
      return(retVal);

    numRead += retVal;
  }

  return(numRead);
}

char readDih(FILE *fp, struct dihType *dihPtr)
{
  size_t retVal;

  retVal = readFull(dihPtr, DIH_SIZE, fp);

  if(retVal <= 0)
    return(CONNECTION_ERROR);

  if(dihPtr->magic != MAGIC_NUMBER)
    return(XFER_ERROR);

  return(OK);
}

The readFull() function fails 'sometimes' when called to read a packet
of data from the serial port which is always 60 bytes.

If anyone can help it would be greatly appreciated.  This controller is
for an "in house" machine that needs to be online ASAP.  This is the
reason it is not online yet!  Please help!  :)


Thanks,

Kyle Rhodes
Hardware / Software Engineer
gh, LLC
3000 Kent Ave
Lafayette, IN 47906
(765) 775-3776  ext 205





More information about the En-Nut-Discussion mailing list