[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [gforth] problem with gforth7 and serial access

From: kibler
Subject: Re: [gforth] problem with gforth7 and serial access
Date: Tue, 03 Apr 2012 14:11:58 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120324 Icedove/10.0.3

On 04/03/12 10:54, Bernd Paysan wrote:
Am Dienstag, 3. April 2012, 09:25:47 schrieb kibler:
In response to the lack of support and some testing on my own,
it appears that serial and probably numerous other functions in
gforth 7 are broken and will remain broken forever.
Maybe.  One thing why you should not boast so loudly about "no support" is
that you did completely fail to show code examples that are broken.  You
showed no code at all.  It is difficult for us to respond seriously to bug
reports without having an easy way to reproduce the bug.  All we then could do
is guess and point you to code that does work on Gforth 0.7.
I got the clear feeling no-one was interested enough to want to see
our code, especially since I had read so many previous emails covering
the same topic without any positive responses. If you think it would make
a difference I will add it to the bottom of the email.

I come to that
conclusion for two reasons - one is that no one has responded
with any proof or code that uses the regular functions in gforth
to handle serial as it was done in gforth 6 - i.e. using existing
functions to access a serial tty port. From my testing it would appear
that the serial interface is now designed to support only console
access and not communications with an embedded product that
might be handling raw data. I see in the updated io.c, key_avail
function, code looking for EOF character, and if found returns "0", or
to say nothing is there.
This is not the EOF character, this is the EOF return value of getc(), which
is -1.  It will be returned when EOF is reached, and is not confused with ^D.
You miss the point, EOF can be any char, it doesn't matter. What matters
is that you are telling my program nothing is available, when in fact there
is one more character - the EOF in this case - and my utilities may be waiting 
that char to close their processes. Thus our code could hang forever waiting
for the EOF that never comes.

Our group realized last week that having gforth 6 work must have been some
bug or bad design problem that got corrected in 7. Having said that, the
fact that select always returns zero we think is a bug and needs understanding
to see what is going on.
Clearly that breaks any form of raw serial
transfers where some binary data might be handled. I suspect there are
other offending code sections, as I saw clear examples of keyboard
handling when I had a print statement in the key_avail code. It showed
that characters were being seen and handled outside the actual
code intended for doing it and thus breaking any true serial I/O.
What did you see?

I put a printf just after select in key_avail and would get a print statement
when ever I entered a key, always "0" even then. If I hit the up arrow on my
keyboard, it redo the previous command without printing anything. When
doing the key?-file call - our key?-s, I saw the keystroke printf and the printf
for the key?-s, always "0", even when I know the file is being hit with a 
stream of chars from our test board. When looking at main in the io.c, that
routine is suppose to have a tight loop checking for key_avail, and as such
I should see a constant stream of printf every time it checks and fails. That
didn't happen, which tells me that some other mechanism is handling keystrokes.

My second concern is based on the fact that all serial code and socket
code examples given in emails, clearly use their own system calls to replace
gforth internal system calls, as everyone has learned that they are broken
and just don't work.
There are other issues.  First of all, Gforth's internal has no way to set
baud rates and line discipline etc.  This you need to roll on your own,
anyways.  So while you are at it, you can just do the rest yourself, too.
Gforth's keyboard handling goes through C's stdio buffers, which is
inappropriate for real serial line handling.

We set serial by doing a system call to stty. We only use gforth system
calls to open/close/read/write/check file handles that happen to be serial
devices. gforth should do those fine without any knowledge of them
being tty, USB, or a socket driver.

This is troubling as it means no one is interested in
fixing internal calls, or that they know they would break too many other
"tweaks" of gforth for some specific platform. It is nice that gforth will
run on so many hardware systems, but troubling that so much hardware
specific coding has been done. The more useful
programs across multiple hardware usually are successful because they
have removed all specific hardware coding and left many platform specific
tasks to the user and not hidden in functions no one would suspect of
doing more than they should (i.e. checking for EOF instead of only returning
a system calls status value).
Well, you misunderstood what this EOF is:  It is the indicaton that the file
has ended, it is not ^D, it is -1.  If the file has ended, there is no further
key available.  Thus the return value of 0 is correct.  The failure of
select() on Linux for serial lines (returns "nothing availabe" when there is
indeed something available) is IMHO a bug in Linux.  ioctl(FIONREAD) does not
work on files, so that is not an option, either - the code in Gforth 0.6 was
broken and had to be replaced.

Our group has several directions to go to work around these issues, but the
main thing we learned is that gforth works well for normal and simple forth
coding. It does not work well for serial and other functions closely
aligned with a systems hardware or OS features. For items like serial, a
roll your own interface is the normal and only option available.
Well, for functions close to the system, use the C interface (libcc.fs).
That's the way to go.  serial.fs is in contrib, it's third party stuff.  As
such, the Gforth autors are not active maintainers of that stuff, and we don't
check if it still works.

Thanks for explaining what we guessed by trying the code - that contrib
code may or may not work - more of a "you need something like this" style
of examples. Which is why I think gforth needs to ship with a known set
of running examples. I will look at libcc.fs, as it appears to be the standard
way now of talking to the system.

---- code overview ---
In this code - only part of several other modules - we setup the serial port
using the "system" call to "stty". We consider this the preferred way of setting
up the serial port - outside of gforth, so that other tools and programs can
talk to our devices once set. The problem is the last routine that uses the
file ID to ask key?-file if some character(s) is waiting to be handled. In 
testing the
code I can read (key-s . ) and see chars from the serial port, but when I do the 
"key?-s . "
it always returns "0".

----- serial-linux.fs ----
0 [if]   serial_ports.fs   Serial Communications in Gforth and Linux.
Copyright (C) 1991-2004 by AM Research, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For LGPL information:

changes for doing baudrate and com port as part of invoking script.
by default it will now do 19200 for com1
do -e " 3 value com?" and -e " 38400 value current-baudrate " to
setup for com3 and 38400...bdk


\ 9600 value current-baudrate  \ download-cygnal.fs, download-ADuC.fs
\ 19200 value current-baudrate  \ download-oldamr.fs
\ 38400 value current-baudrate   \ Silicon Labs 120.

: has  (  - flag) BL word find nip 0<> ; immediate
has com? 0= [if]  1 value com?  [then]
has current-baudrate 0= [if]  19200 value current-baudrate  [then]

\ a list of four strings
here ," /dev/ttyS3"
here ," /dev/ttyS2"
here ," /dev/ttyS1"
here ," /dev/ttyS0"
create 'portnames   , , , ,

: "portname   (  - a u)
    com? 4 min 1 max 1- cells 'portnames + @ count ;

: .port  (  - )  "portname type ." > " ;

\ Newer versions of stty allow the -F option to configure a serial port
\ other than the one you're using for your terminal.  Older versions
\ accomplish the same thing with < for redirecting input from the serial
\ port.  The version with < probably works for all systems.
\ : "stty   (  - a u)   s" stty < " ;
: "stty   (  - a u)   s" stty -F " ;
: "a      (  - a u)   s"  -a ";

: get_stty ( - ??? )
    "stty pad place   "portname pad +place
    "a pad +place   pad count system ;

: "N81   (  - a u)
    s"  -parenb cs8 -cstopb -crtscts raw -echo" ;

: n81   (  - )
    "stty pad place   "portname pad +place
    "N81 pad +place   pad count system ;

: baud   ( n - )
    "stty pad place   "portname pad +place
    0 <# #s bl hold #> pad +place   pad count system ;

variable serial-fid

: ?serial-problem   ( error-code - )
    ?dup if   cr .error abort   then ;

: (open-comm)   ( n - )
    N81 ( n) baud
    "portname r/o open-file ?serial-problem serial-fid ! ;

: open-comm   (  - ) current-baudrate (open-comm) ;

: close-comm   (  - )   serial-fid @ close-file drop ;

warnings off
: bye   (  - )   serial-fid @ if   close-comm   then   bye ;
warnings on

: port   ( n - )
    create    ,
    does>    close-comm @ to com? open-comm ;
1 port com1
2 port com2
3 port com3
4 port com4

: key-s   (  - c)
    pad 1 serial-fid @ read-file 0= 1 and - ?serial-problem
    pad c@ ;

: key?-s   (  - flag)
    serial-fid @ key?-file ;

: emit-s   ( c - )
    "portname w/o open-file ?serial-problem
    tuck emit-file ?serial-problem close-file ?serial-problem ;

: type-s  ( addr len - ) 0 do  count emit-s  loop  drop ;

: clear-sbuf   (  - )   begin   key?-s while   key-s drop   repeat ;

---- end code ----

reply via email to

[Prev in Thread] Current Thread [Next in Thread]