Click to See Complete Forum and Search --> : SIGIO interrupt and Asychronous Serial
tecknophreak
08-02-2001, 09:59 AM
I know, no one here prolly knows the answer. I couldn't find it else where. I'm trying to create an interrupt everytime a char comes across the serial port(Null Modem). The only problem is that it only creates an interrupt when a carrage return is sent across. So the serial buffer holds the chars coming across until the cr is sent. The buffer also holds data while it's waiting for real char data from the other comp!
Setting up the signal:
sigset_t mask;
sfd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (sfd < 0) {
perror(MODEMDEVICE);
exit(1);
}
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO, &saio, NULL);
fcntl(sfd, F_SETOWN, getpid());
fcntl(sfd, F_SETFL, FASYNC);
interrupt handler
void signal_handler_IO (int status) {
wait_flag = 0;
cout << "got a char" << endl;
}
It only says "got a char" if i hit the carrage return on the other comp.
Other notes, I tried a connection between the two to see if the other comp only sends data after a carrage return. Using minicom i found it did not. The program on the other comp is procomm.
[ 02 August 2001: Message edited by: tecknophreak ]
augur
08-02-2001, 10:19 AM
Greetings,
Actually i do not know the answer, but i found this, wich may contain the answer for you, its minicom.c:
/*
* AUTHOR: Sven Goldt (goldt@math.tu-berlin.de)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
This is like all programs in the Linux Programmer's Guide meant
as a simple practical demonstration.
It can be used as a base for a real terminal program.
*/
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/modem"
#define ENDMINITERM 2 /* ctrl-b to quit miniterm */
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
void child_handler(int s)
{
STOP=TRUE;
}
main()
{
int fd,c;
struct termios oldtio,newtio,oldstdtio,newstdtio;
struct sigaction sa;
/*
Open modem device for reading and writing and not as controlling tty
because we don't want to get killed if linenoise sends CTRL-C.
*/
fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY);
if (fd <0) {perror(MODEMDEVICE); exit(-1); }
tcgetattr(fd,&oldtio); /* save current modem settings */
/*
Set bps rate and hardware flow control and 8n1 (8bit,no parity,1 stopbit).
Also don't hangup automatically and ignore modem status.
Finally enable receiving characters.
*/
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/*
Ignore bytes with parity errors and make terminal raw and dumb.
*/
newtio.c_iflag = IGNPAR;
/*
Raw output.
*/
newtio.c_oflag = 0;
/*
Don't echo characters because if you connect to a host it or your
modem will echo characters for you. Don't generate signals.
*/
newtio.c_lflag = 0;
/* blocking read until 1 char arrives */
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
/* now clean the modem line and activate the settings for modem */
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
/*
Strange, but if you uncomment this command miniterm will not work
even if you stop canonical mode for stdout. This is a linux bug.
*/
tcsetattr(1,TCSANOW,&newtio); /* stdout settings like modem settings */
/* next stop echo and buffering for stdin */
tcgetattr(0,&oldstdtio);
tcgetattr(0,&newstdtio); /* get working stdtio */
newstdtio.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0,TCSANOW,&newstdtio);
/* terminal settings done, now handle in/ouput */
switch (fork())
{
case 0: /* child */
/* user input */
close(1); /* stdout not needed */
for (c=getchar(); c!= ENDMINITERM ; c=getchar()) write(fd,&c,1);
tcsetattr(fd,TCSANOW,&oldtio); /* restore old modem setings */
tcsetattr(0,TCSANOW,&oldstdtio); /* restore old tty setings */
close(fd);
exit(0); /* will send a SIGCHLD to the parent */
break;
case -1:
perror("fork");
tcsetattr(fd,TCSANOW,&oldtio);
close(fd);
exit(-1);
default: /* parent */
close(0); /* stdin not needed */
sa.sa_handler = child_handler;
sa.sa_flags = 0;
sigaction(SIGCHLD,&sa,NULL); /* handle dying child */
while (STOP==FALSE) /* modem input handler */
{
read(fd,&c,1); /* modem */
write(1,&c,1); /* stdout */
}
wait(NULL); /* wait for child to die or it will become a zombie */
break;
}
}
Hope this helps.
tecknophreak
08-02-2001, 01:40 PM
No, the signal is on the child. MiniCom waits until it gets a char then returns it. My program has to be prompted to do that by an interrupt. I'll be doing one thing and then I'll need to catch the serial data when it comes in so I don't lose any. I can't just poll the port once a loop.
Thanks anyway!
augur
08-03-2001, 05:29 AM
Greetings,
I never did serial programming under linux, so i'm afraid i can't be much help, but i have another link for you: Index of /public/ftp/pub/Linux/system/serial (http://www.ibiblio.org/pub/Linux/system/serial/!INDEX.short.html)
tecknophreak
08-03-2001, 09:26 AM
Thanks, [Chris Farley] I'll....Check it out[/Farley]
tecknophreak
08-06-2001, 09:20 AM
Nothing good there. ummmm.... there seems to be something wrong here. I'll have to check out some things.
pinoy
08-06-2001, 06:05 PM
Couldn't you use a select? That would probably return as soon as there is data in the buffer. I can't verify it for you as I have no UNIX box at the moment. Otherwise why not start a separate thread to poll for the serial port and raise a condition for the main thread as soon as data arrives.