Skip site navigation (1)Skip section navigation (2)
Date:      06 Aug 2003 16:19:58 -0400
From:      "J. Seth Henry" <jshamlet@comcast.net>
To:        Michael Conlen <meconlen@obfuscated.net>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: FreeBSD programming question
Message-ID:  <1060201196.55618.9.camel@alexandria>
In-Reply-To: <3F313E32.9060908@obfuscated.net>
References:  <1060119004.53095.25.camel@alexandria> <200308062328.38914.malcolm.kay@internode.on.net> <3F313E32.9060908@obfuscated.net>

next in thread | previous in thread | raw e-mail | index | archive | help
That looks exactly like what I want. I need to resume programming on
either serial activity and at periodic intervals. Eventually, I plan to
toss networking into the mix, and this program will function as a
daemon, but I'm relatively new to programming for *nix (though not new
to programming in general), so I'm going to steer clear of that until I
get the basic IO working.

I've already written, and for the most part debugged, my configuration
file parser, and this was the next step. :)

When I finish, I want to be able to check the status, and control, the
HVAC system from any terminal on the network. 

Thanks again  for the help,
Seth Henry

On Wed, 2003-08-06 at 13:43, Michael Conlen wrote:
> select() should work for you, similar to trigering an interrupt. Instead 
> of triggering an ISR select() will sleep until there's an event on the 
> file descriptors. So you open() the device for the serial port and 
> select() on it. When you return from select() the return value will tell 
> you why you returned and you handle the situation similar to programing 
> for the 8250 (read from the port to see which event).
> 
> In any case, you can select() on the file descriptors for the standard 
> input and the serial port, though remember that STDIN uses buffered IO 
> and open() will return an unbuffered file descriptor, which is what 
> select() uses, so you need to find the unbuffered file descriptor for 
> the stadard IO, which is either 0, 1 or 2, but I forget which on FreeBSD 
> (I've been doing network daemons to much lately).
> 
> In any case, you create an FD_SET
> 
> fd_set mySet;
> FD_ZERO(&mySet);
> FD_SET(fd, &mySet);
> 
> where fd is the file descriptor returned from open, or the file 
> descriptor for the standard input.
> 
> Use the set as a read set with select along iwth a timeout. struct 
> timeval is
> 
> struct timeval {
>         long    tv_sec;         /* seconds */
>         long    tv_usec;        /* and microseconds */
> };
> 
> if the pointer to the struct timeval is NULL then it waits forever. (or 
> until a signal causes an exit).
> 
> (Note, usleep() is often implemented using select on no file descriptors 
> and a timeval).
> 
> int rc;
> struct timeval myTimeout;
> rc = select(2, &mySet, NULL, NULL, &myTimeout);
> 
> This call will return when either timeval is up or there's data to read 
> on your file descriptors. Be sure to check errno if select returns -1. 
> When select returns the fd_set will be set to the descriptors that are 
> actionable. Use FD_ISSET(fd, &mySet) to see if that file descriptor is 
> waiting to be actioned on (read, write, or other) until you've found all 
> the ones that are ready (the number returned by select()) and do your thing.
> 
> There's a really great book called "Advanced Programing in the UNIX 
> environment" and it will show you all the system calls you ever needed 
> to know to work with UNIX, though it's light on the concurrency issues, 
> but it doesn't sound like your writing multithreaded memory shared 
> programs so it's no worry.
> 
> I haven't really looked at the sio driver, but I doubt it, it still 
> works with the 8250, which only had one IO address (tell it what you 
> want to do, read the result, tell it what you want to do, send it info, 
> tell it what you want to know, read the info it has... ...programing was 
> much more fun back then).
> 
> 
> 
> 
> J. Seth Henry wrote:
> 
> >It appears that my experience on microcontrollers is throwing me off.
> >I'm used to having a touch more control at the hardware level.
> >
> >It sounds like I would be best served by setting up a loop that sleeps
> >for a certain number of milliseconds, and then looks for new data in the
> >serial port buffers. Knowing the amount of time per loop, I could handle
> >the periodic data polling as well. My largest concern was in creating a
> >CPU hog. I don't want to slow the system down by constantly accessing
> >the serial port.
> >
> >It occurred to me that I may be able to deal with this another way. I
> >can poll the thermostat for MOST things, only the user interface
> >requires fairly speedy interactions. I can simply listen for the "ENTER"
> >button, and then increase the polling rate until the UI exits.
> >
> >As it were, I'm poking around in the ports to see how other programs
> >have dealt with this.
> >
> >Just out of curiousity, since I can check the driver source, does the
> >sio driver add any additional buffering, or does it simply read the
> >16byte FIFO on the serial port? Most of the messages I am expecting
> >should fit in that FIFO anyway.
> >
> >Thanks,
> >Seth Henry
> >
> >On Wed, 2003-08-06 at 09:58, Malcolm Kay wrote:
> >  
> >
> >>On Wed, 6 Aug 2003 07:00, J. Seth Henry wrote:
> >>    
> >>
> >>>Not sure if this is the right list or not, but I could really use some
> >>>pointers.
> >>>
> >>>How can I code trap serial port interrupts in my C program?
> >>>
> >>>      
> >>>
> >>For any modern hosted system interrupt trapping and servicing is in the 
> >>province of the system -- it should not be a userland activity.
> >>
> >>    
> >>
> >>>For example, I want to read values from a serial device every
> >>>user-specified number of seconds, calculate some stuff and then sit for
> >>>a while. Should the serial device decide it wants to send some data
> >>>unsolicited, I would like to enter an interrupt service routine, handle
> >>>the communication, and then return to the previous loop.
> >>>      
> >>>
> >>There are a number of techniques which may or may not suit your needs;
> >>it is not too clear just what you are trying to do.
> >>
> >>Generally the system will provide some buffering of input so it is not usually
> >>important that your code processes each character immediately on arrival.
> >>
> >>In many cases using placing the select(2) system call in a loop will meet the 
> >>needs.
> >>
> >>In more difficult cases you may need to look at threading pthread(3) or 
> >>forking fork(2) or vfork(2)
> >>
> >>    
> >>
> >>>I can get the loop going by using sleep(n), but I don't know how to
> >>>write the ISR in C, and (additionally) make it such that it will run on
> >>>any *nix like platform.
> >>>      
> >>>
> >>You might be able to do something at system level by adding your driver to the 
> >>kernel possibly as a kernel module. This is not generally the way to go if 
> >>userland alternatives work and it certainly will be very operating system and 
> >>platform specific possibly even requiring significant editing from one OS 
> >>version to the next.
> >>
> >>    
> >>
> >>>Any pointers, HOWTO's, or examples would be greatly appreciated!
> >>>
> >>>Thanks,
> >>>Seth
> >>>
> >>>      
> >>>
> >>Malcolm Kay
> >>
> >>    
> >>
> >
> >_______________________________________________
> >freebsd-questions@freebsd.org mailing list
> >http://lists.freebsd.org/mailman/listinfo/freebsd-questions
> >To unsubscribe, send any mail to "freebsd-questions-unsubscribe@freebsd.org"
> >  
> >
> 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1060201196.55618.9.camel>