This is the mail archive of the ecos-discuss@sourceware.cygnus.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]

Re: Serial I/O on the MBX860


On Thu, 3 Feb 2000, Erik Theisen wrote:

> Hi,
> 
> I have been trying to get stdin working on
> the MBX860 using fgets().  This seems to result in
> a hung CPU.
> 
> How do I make stdin work?

Hi Erik,

In a nutshell, I think line buffering is broken in the eCos stdiostream
code. 

Try entering several lines of text until you pass 256 bytes, and
see if your code continues after that.

In a test program of mine, the call stack during a call to fgets() 
is,

#0  0x6d4 in serial_read (handle=0x97a4, _buf=0xa114, len=0xc3f0)
    at
/usr/local/ecos-1.2.1/packages/io/serial/v1_2_1/src/common/serial.c:161
#1  0xa20 in cyg_io_read (handle=0x97a4, buf=0xa114, len=0xc3f0)
    at /usr/local/ecos-1.2.1/packages/io/common/v1_2_1/src/iosys.c:182
#2  0x4869 in Cyg_StdioStream::refill_read_buffer (this=0xa108)
    at
/usr/local/ecos-1.2.1/packages/language/c/libc/v1_2_1/src/stdio/common/stream.cxx:248
#3  0x4eb2 in _fgets (s=0xc430 "", n=128, stream=0xa108)
    at
/usr/local/ecos-1.2.1/packages/language/c/libc/v1_2_1/src/stdio/input/fgets.cxx:77
#4  0x38 in main () at testcase.c:14
#5  0x78fb in cyg_libc_invoke_main ()
    at
/usr/local/ecos-1.2.1/packages/language/c/libc/v1_2_1/src/support/invokemain.cxx:82
#6  0x1ca1 in Cyg_HardwareThread::thread_entry (thread=0xa448)
    at
/usr/local/ecos-1.2.1/packages/kernel/v1_2_1/src/common/thread.cxx:92
#7  0xdeadbeef in ?? ()


At level #0, the code in serial_read() is doing,

        while (size++ < *len) {
            *buf++ = (funs->getc)(chan);
        }


where *len is 256.  Not only is there no check for \r or \n,
but serial_read() intends to read 256 characters when I only
asked for 128 in fgets.

Same thing happens in fgetc.

Where did the 256 come from?  Go up a few more levels.

serial_read (handle=0x9784, _buf=0xa0f4, len=0xc3d4)
cyg_io_read (handle=0x9784, buf=0xa0f4, len=0xc3d4)
Cyg_StdioStream::refill_read_buffer (this=0xa0e8)  <=======
_fgetc (stream=0xa0e8)
main ()
cyg_libc_invoke_main ()


In Cyg_StdioStream::refill_read_buffer(), when flags.buffering
is set, "len" is assigned 256 here,

    if (flags.buffering) {
        len = io_buf.get_buffer_addr_to_write( (cyg_uint8**)&buffer );
        if (!len) { // no buffer space available
            unlock_me();
            return ENOERR;  // isn't an error, just needs user to read out
data
        } // if
    }


You can try setvbuf(_IONBF), but I think that does something weird,
too.

The test program is below, try defining TEST1 or TEST2 (not both)
and see what happens.

I reported this to my former supervisor (before I became
the Cygnus contact on the project) but he might have
failed to report it to Cygnus.  I started fiddling with the 
serial port after I encountered this so I kind of forgot about
it.

-Jamie

---------------------------------------------------------------

/*
 * testcase.c stdio input test case
 */

#include <stdio.h>

#define TEST1

int main()
{
  char buffer[128];
#ifdef TEST1
  char bufx[512];
#endif

#ifdef TEST1
  setvbuf(stdin, bufx, _IOLBF, sizeof(bufx));
#endif

#ifdef TEST2
  setvbuf(stdin, NULL, _IONBF, 0);  
#endif

  while (1)
    {
      printf("$ ");
      fflush(stdout);
      fgets(buffer, sizeof(buffer), stdin);
      printf("you entered: %s\n", buffer);
    }
  return 0;
}



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