This is the mail archive of the
ecos-discuss@sourceware.cygnus.com
mailing list for the eCos project.
Re: Serial I/O on the MBX860
- To: Erik Theisen <etheisen at mindspring dot com>
- Subject: Re: [ECOS] Serial I/O on the MBX860
- From: Jamie Guinan <guinan at bluebutton dot com>
- Date: Thu, 3 Feb 2000 05:32:37 -0500 (EST)
- cc: ecos-discuss at sourceware dot cygnus dot com
- Reply-To: guinan at bluebutton dot com
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;
}