This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Serial read problems


Hello group,

I'm trying to have an ARM AEB C board communicate with a GSM
modem attached to its secondary serial port via Cyg I/O functions.
While this works in principle, reading from the port following
a write operation (with and without intermediate drain) tends
to systematically skip characters in the received input.  This
means that (depending on what the exact sequence of instructions
looks like and what it does intermediately), a number of leading
characters (2 through 5, occasionally more) are mysteriously
missing from the input buffer.  Also, occasionally, intermediate
subsequences of characters are skipped.  For example, the
original text:

  FOOBAR FOO BAR BAZ

might end up like this:

  AR FOO B BAZ

A simple test program exhibiting said effect:

  #include <cyg/kernel/kapi.h>
  #include <cyg/io/io.h>
  #include <cyg/io/serialio.h>
  #include <cyg/hal/hal_intr.h>
 
  int
  main()  
  {
    char c;
    cyg_io_handle_t h;
    cyg_uint32 i;
    cyg_serial_info_t si;

    cyg_io_lookup("/dev/ser0", &h);
    si.baud = CYGNUM_SERIAL_BAUD_9600;
    si.word_length = CYGNUM_SERIAL_WORD_LENGTH_8;
    si.stop = CYGNUM_SERIAL_STOP_1;
    si.parity = CYGNUM_SERIAL_PARITY_NONE;
    si.flags = 0;
    i = sizeof(si);
    cyg_io_set_config(h, CYG_IO_SET_CONFIG_SERIAL_INFO, &si, &i);
    cyg_io_get_config(h, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, 0, 0);
    i = 4;
    cyg_io_write(h, "ATI\r", &i);
    cyg_io_get_config(h, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, 0, 0);
    for(;;) {
      int res;

      i = sizeof(buf)-1;
      res = cyg_io_read(h, buf, &i);
      if (res != ENOERR && res != -EAGAIN) continue;
      buf[i] = '\0';
      if (i) printf("%s", buf);
    }
  }

Note that the effect is unaffected by whether or not reading is
set to be blocking or non-blocking.

The only way to work around the problem I've discovered so far
consists in inserting a sufficiently long cyg_thread_delay()
(100ms) in between the calls to cyg_io_write() and cyg_io_read()
and consecutive calls of the latter, respectively.  Seems like
this supplies whatever is happening internally with just the
runtime needed to cope with the situation at hand.  Still, this
workaround is merely a kludge that can't seriously be considered
a solution.

According to my understanding, the problem could be explained by
assuming that the ISR/DSR handling of the serial operations is
for some reason unable to keep up with the rate data is received
(note that the board has but a one-byte receive register and an
8-bit shift buffer, i.e., no FIFO).  However, since the effect
happens even at 9,600 baud and without the test program doing
anything much...  I'd expect the board to be able to handle
_that_.

It might furthermore be interesting to note that about the same
applies to a similarly-outfitted NEC-V850-type board, with the
added effect of characters ill-received as the preceding one,
i.e.:

  ABCDEFGHIJK

might, e.g., become

  GGIIJK

This even happens with one of the standard tests (flow1) on
a CEB board.  This test utilizes the test_ping() function which
uses custom I/O routines to receive an "OK" response--which is
instead received as "KK".

Seems like the receive register is updated in between the
invocation of the ISR and the DSR.

I've tried various recent snapshots and CVS checkouts of eCos
(including one of Aug 20th and a current checkout), with no
change in effects.


I'd be grateful for any hints as to what might be the exact 
cause of the problem and how to resolve it.


Marco
-- 

-------------------------------------------------
This mail sent through IMP: imp.imms.de


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]