RetroBSD

2.11BSD operating system for microcontrollers
It is currently Sun Mar 29, 2020 11:48 am

All times are UTC




Post new topic Reply to topic  [ 53 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: retrobsd char is ready
PostPosted: Wed Dec 02, 2015 3:13 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

I am looking for a way to tell that a incoming tty char is ready?

I see that getchar() is passed up the chain to getc(stdin).

Looking through the code I don't see any way to poll whether an incoming tty char [from whatever device] is ready? Maybe I just haven't guessed the function? Maybe it is available as an ioctl function?

My work around at this point is to read the UART status word. But it seems like there 'ought to be' a right way to do this?

My program wants to spin around its idle loop until a key is struck.

There 'must' be a 'right' way to do this :).

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Wed Dec 02, 2015 4:29 pm 
Committer
User avatar

Joined: Thu Oct 11, 2012 8:45 am
Posts: 1801
Location: Room 217, Floor 8, Arm 8, Wheel S7, Mars Base Alpha 3
If you're talking about userland coding, then the function you want is "select":

Quote:
select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2) without blocking, or a sufficiently small write(2)).


Example from Linux:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval;

    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);

    /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

    retval = select(1, &rfds, NULL, NULL, &tv);
    /* Don't rely on the value of tv now! */

    if (retval == -1)
        perror("select()");
    else if (retval)
        printf("Data is available now.\n");
        /* FD_ISSET(0, &rfds) will be true. */
    else
        printf("No data within five seconds.\n");

    exit(EXIT_SUCCESS);
}

You may need to adjust it slightly for RetroBSD, but it gives you the general methodology.

_________________
Why not visit my shop? http://majenko.co.uk/catalog
Universal IDE: http://uecide.org
"I was trying to find out if it was possible to only eat one Jaffa Cake. I had to abandon the experiment because I ran out of Jaffa Cakes".


Top
 Profile  
 
PostPosted: Wed Dec 02, 2015 8:12 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Matt,

Thanks :).

There are two usage examples in Retro that I found:

getty and pforth. So at least these compiled :).

So maybe I can get it running from there.

I guess some working examples might be in order in our docs?

Thanks again,

Wiz


Top
 Profile  
 
PostPosted: Wed Dec 02, 2015 8:20 pm 
Committer
User avatar

Joined: Wed Oct 10, 2012 11:01 pm
Posts: 1081
Location: Sunnyvale, CA
majenko wrote:
If you're talking about userland coding, then the function you want is "select":

Select call is the most universal method, as it allows polling several descriptors at once. Another choice is FIONREAD ioctl. It returns a number of input bytes available for read on any file descriptor:
Code:
    char input;
    int nchars;

    ioctl(0, FIONREAD, &nchars);
    if (nchars <= 0)
        input = -1; /* no input */
    else
        read(0, &input, 1);


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 2:09 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Serge and Matt,

Thanks.

I gather I could test with the ioctl method and then call getchar to get the chars? Thus I would only have to add one line to my current code. I will try that.

I will also try the select method.

The 'worm' game does read(0,&ch,1) >=0 to test for input and then get it if it is there.

I couldn't seem to get it to work but it might have been typing error on my part?

At least it compiled :).

I will try the other 2 methods as see what I can get to work. I am using a rather old kernel since it has my real-time patches in it. So that might be an issue as well?

IMHO the whole business needs to be made more user friendly. Especially regards use of 'idle time' and 'clock ticks' by real user programs. Both seem very much at odds with what one usually does when making programs run real-time. My kernel has both of those places with patch availability. Seems to work OK.

Then again I am probably just preaching to the chior :).

Thanks again.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 4:17 pm 
Committer
User avatar

Joined: Thu Oct 11, 2012 8:45 am
Posts: 1801
Location: Room 217, Floor 8, Arm 8, Wheel S7, Mars Base Alpha 3
Unless you specify non blocking when you open the file or use fcntl to switch on non blocking then read will wait until a character is ready. With non blocking enabled read will return -1 if there is nothing to read.

Sent from my SM-T555 using Tapatalk

_________________
Why not visit my shop? http://majenko.co.uk/catalog
Universal IDE: http://uecide.org
"I was trying to find out if it was possible to only eat one Jaffa Cake. I had to abandon the experiment because I ran out of Jaffa Cakes".


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 7:31 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Serge and Matt,

Today seems to be flake day....

Even int main(void) {return 0; ... }

and int main(void) {exit; ... } don't seem to work right?

Illegal instruction - core dumped. {return 0;}

or total system restart in the case of {exit; ... }

Ugh!

Maybe program is too big and some system stuff gets overwritten?

This sort of thing in my mind really tests our system debug tools. Is there enough information provided so that the 'real' problem can be identified and fixed?

After the 'exit' only ctl-c and 'enter' work from the keyboard. No commands seem to be able to be typed to the system (like reboot). So its power down time and hope the SD has not been corrupted.

Are we having fun yet?

{ I am using a very old kernel.... }

All this to try to get chrrdy to really work!

Lots of fun :).

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 8:36 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

The latest surprise:

puts("test");

Does not put anything out to the tty!

until puts("\n"); Ugh. I did turn the tty to RAW mode.

I remember some early DOS program where I finally gave up and drove the UART from BASIC script to avoid OS "help".

Do I really need to do that here?

At least my LEDs turn on and off when they should [ I think? ].

I guess I could turn off the interrupts and use I/O pins for my uart link. Yikes.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 8:56 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

The 'latest' ...

puts(xtoa(ioctl(0,FIONREAD,&temp) always returns 0 ??!!

Does not change when characters are typed and 'should' be ready.

puts(xtoa(ioctl(MemoryRead(0xbf806030))) returns tty character codes but they don't seem to be changing to what I recently type.

Not sure what could be happening here. Maybe the uart has a multi character buffer so I am not seeing characters as they are typed?

puts(xtoa(ioctl(MemoryRead(0xbf806010))) always returns 00001510 this location should have uart flags. I NEVER see the char ready bit [b0] true? Is the uart under interrupt control? If so I would not expect to see buffered characters as above!

A bit bang uart is starting to look very interesting.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 10:00 pm 
Committer
User avatar

Joined: Thu Oct 11, 2012 8:45 am
Posts: 1801
Location: Room 217, Floor 8, Arm 8, Wheel S7, Mars Base Alpha 3
You don't interact with the UART directly. You interact with the TTY device. The UART interrupt passes the characters directly to the input pipe of the tty driver which then does whatever needs doing in the way of cooking it etc and then places it into its own buffer. Only then does it get sent on to your program. It's quite a complex system and not something you can easily tinker with.

Sent from my SM-T555 using Tapatalk

_________________
Why not visit my shop? http://majenko.co.uk/catalog
Universal IDE: http://uecide.org
"I was trying to find out if it was possible to only eat one Jaffa Cake. I had to abandon the experiment because I ran out of Jaffa Cakes".


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 10:15 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

Well it finally begins to make sense....

Apparently the chip's RX data available bit can be inverted.

So the 00001510 means that the data available bit has been inverted.

And the UART buffers 4 characters. So apparently RetroBSD is not taking characters from the UART unless getchar has been called and it is looping awaiting data.

No wonder there are no characters waiting via ioctl. The input characters have not been read!

Maybe this has been 'fixed' in more recent versions of the kernel?

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 11:03 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Matt,

"Not easily tinkered with".

I have been looking at the code. Yup, seems pretty obscure to me also.

Reading the registers as I type has certainly gotten me wondering how it really works. Multiple reads of 6030 seem to give the same character over and over. Maybe the 4 character buffer mode is not enabled?

I guess the tty routine may be running from interrupts.

Who knows?? I just want to know when there is a character ready.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Thu Dec 03, 2015 11:07 pm 
Committer
User avatar

Joined: Thu Oct 11, 2012 8:45 am
Posts: 1801
Location: Room 217, Floor 8, Arm 8, Wheel S7, Mars Base Alpha 3
Yes, interrupts are used, and triggered from the main handler in exception.c.

Sent from my SM-T555 using Tapatalk

_________________
Why not visit my shop? http://majenko.co.uk/catalog
Universal IDE: http://uecide.org
"I was trying to find out if it was possible to only eat one Jaffa Cake. I had to abandon the experiment because I ran out of Jaffa Cakes".


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 2:17 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

I keep thinking about Matt's "not easily tinkered with" comment.

I guess that is my problem as well?

I 'just' want to write a simple program that responds to keystrokes and displays some other data that changes by itself from time to time.

Apparently RetroBSD has a hard time doing that??!! Kinda amazing.

I was reading a man page about select that showed a 'simple' way to interconnect two TCP connections. That page did not appear simple to me.

So let's see I pick up the telephone and dial a number and talk. 64kbps travel both ways. Not a problem.

Am I to believe that RetroBSD has a hard time with this? I guess the language makes this appear to be difficult?

It certainly HAS been difficult for me to get my simple program to work usefully.

All I was trying to do is to talk to my newly acquired WiFire board and read what is in its flash as sent from the factory using the ICSP protocol from my RetroBSD system.


WE MUST make our system useful and easy for doing this kind of thing. This kind of thing IS EASY in assembly code!!

I did monitor the ioctl that Serge suggested. It is never non-zero?? So I guess there is some kind of a bug. Perhaps some simple misunderstanding on my part?

Bit bang serial with interrupts turned off looks like the ONLY answer at this point to me. Kinda thought provoking and disturbing to me. Abandon RetroBSD so I can just send and receive simple serial characters?

I am not sure I should post this?

I feel like I MUST be missing an easy answer?

Then again maybe I am trying to do something that RetroBSD just cannot do or cannot do easily?

Comment most welcome.

Lots of fun :).

Wiz


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 2:54 pm 
Committer
User avatar

Joined: Thu Oct 11, 2012 8:45 am
Posts: 1801
Location: Room 217, Floor 8, Arm 8, Wheel S7, Mars Base Alpha 3
The thing you are lacking is the basic concepts about how to program in a Unix environment.

You are still trying to program the chip instead of programming the operating system. As a result you are fighting against the operating system all the way, and it's not working.

Step 1: Rorget completely that you happen to be on a PIC32. You are not on a PIC32, you are on a BSD operating system. If you insist on trying to program a PIC32 when you are on a BSD operating system you are doomed to failure. The ONLY thing that should even ever have an inkling that you are on a PIC32 is the kernel, and that has absolutely nothing to do with your user-land program.

Step 2: Read up on the standard Unix tools for IO. That means terminal control systems (somewhat primitive in RetroBSD alas - but much better in LiteBSD) such as Termcap and Curses / NCurses. Learn what RAW and COOKED modes are, what CBREAK means, etc.

Step 3: Write a program for the OS, not the chip. A well written program will work just the same on RetroBSD, LiteBSD and FreeBSD, and even Linux, without any or many changes.

_________________
Why not visit my shop? http://majenko.co.uk/catalog
Universal IDE: http://uecide.org
"I was trying to find out if it was possible to only eat one Jaffa Cake. I had to abandon the experiment because I ran out of Jaffa Cakes".


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 8:29 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Serge and all,

Given that ioctl FIONREAD does not give the number of input characters waiting. And digging a little deeper....

FIONREAD has the value of 0x40046661. Which codes how ioctl is supposed to access the number of chars waiting.

The information I am looking for is [imho] stored in RAM in at array called uartttys which starts at 0x80005c48 in the version of the kernel I am using.

I am not too good at reading header files, but the information for the first uart begins there and seems to be stored from 0x80005c48 up to 5f14. [The rest of this array is zero.]

Somewhere in there is the number of pending input characters that I am looking for :).

Perhaps someone is better at reading header files than I am?

But it is CERTAINLY nice to be able to examine RAM in my running RetroBSD system :). Once I can read that there are pending characters, I can fix my debugger so it is [MUCH] more useful :).

And I can get to work doing real i/o for my ICSP program.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Fri Dec 04, 2015 9:51 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Serge and all,

Wheeeee.

The number of characters is stored at 0x80005c48. At least for the first uart.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Sat Dec 05, 2015 11:59 am 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi All,

Well....

Things are more or less working :).

Apparently ioctl is not working correctly. Maybe this is the cause of most of my problems. I also note that setting tty to raw is also not working?

I just tried a different version of smlrc thinking that that might fix things. Same symptoms.

Next I will try the most recent binary of smlrc.... Thanks to Serge's binaries.

Stay tuned.

Lots of fun.

Wiz


Top
 Profile  
 
PostPosted: Sat Dec 05, 2015 10:22 pm 
Contributor

Joined: Mon Nov 12, 2012 1:34 pm
Posts: 1092
Hi Serge and Matt and All,

So all is working except.... [ Old story :). ]

Reading 0x80005c48 does tell the number of pending characters ready for input :).

If I call getchar() after a character is ready, I get the character as expected.

If, however, I try to echo that character by calling putchar(charin), there is no character output??!! The output program waits until the next \n to put characters out??!!

Must be some fancy feature left over from some serial terminal somewhere?

I have yet to find out where this is done or if there is a flag to turn off this 'feature'. RAW and friends don't seem to do the trick.

Anyone have any ideas?

Lots of fun :).

Wiz


Top
 Profile  
 
PostPosted: Sun Dec 06, 2015 12:58 am 
Contributor

Joined: Mon Apr 29, 2013 1:56 am
Posts: 196
stdout can be line buffered (interactive devices) or fully buffered (actual files). If you want to make sure your buffered data is transferred to the system, you should either use fflush(stdout) or at the very beginning of your program (before using stdout) switch stdout to unbuffered mode by using setbuf(stdout, NULL). This is as far as the language is concerned. All other buffering is in the drivers and the kernel.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 53 posts ]  Go to page 1, 2, 3  Next

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
cron




Powered by phpBB® Forum Software © phpBB Group

BSD Daemon used with permission