2013-02-27 5 views
7

Я пытаюсь установить прерывание для последовательного порта в ubuntu (в программе, написанной на C), но это не работает. Я проверил, что последовательная связь работает правильно без прерывания, поэтому я могу установить что-то неправильно. код выглядит следующим образом:установка прерывания последовательного порта в linux

#include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <unistd.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <fcntl.h> 
    #include <sys/signal.h> 
    #include <errno.h> 
    #include <termios.h> 

    void signal_handler_IO (int status); /* definition of signal handler */ 

    int n; 
    int fd; 
    int connected; 
    struct termios termAttr; 
    struct sigaction saio; 

    int main(int argc, char *argv[]) 
    { 
     fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); 
     if (fd == -1) 
     { 
      perror("open_port: Unable to open /dev/ttyO1\n"); 
      exit(1); 
     } 

     saio.sa_handler = signal_handler_IO; 
     saio.sa_flags = 0; 
     saio.sa_restorer = NULL; 
     sigaction(SIGIO,&saio,NULL); 

     fcntl(fd, F_SETFL, FNDELAY); 
     fcntl(fd, F_SETOWN, getpid()); 

     tcgetattr(fd,&termAttr); 
     baudRate = B115200; 
     cfsetispeed(&termAttr,B115200); 
     cfsetospeed(&termAttr,B115200); 
     termAttr.c_cflag &= ~PARENB; 
     termAttr.c_cflag &= ~CSTOPB; 
     termAttr.c_cflag &= ~CSIZE; 
     termAttr.c_cflag |= CS8; 
     termAttr.c_cflag |= (CLOCAL | CREAD); 
     termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
     termAttr.c_iflag &= ~(IXON | IXOFF | IXANY); 
     termAttr.c_oflag &= ~OPOST; 
     tcsetattr(fd,TCSANOW,&termAttr); 
     printf("UART1 configured....\n"); 

     connected = 1; 
     while(connected == 1){ 
       // some code 
     } 

     close(fd); 
     exit(0);    
    } 

    void signal_handler_IO (int status) 
    { 
     printf("received data from UART.\n"); 
    } 

Так время любое другое устройство, отправить сообщение через заданный порт, сообщение «получил данные от UART.» никогда не отображается.

Любые предложения по решению этой проблемы? Кроме того, как система связывает прерывание с последовательным портом ?, я прочитал о сигнале.h, но я не нашел для этого ответа. Я получил идею прерывания с этой страницы: http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html

Заранее благодарим за любую помощь. Спасибо заранее.

+0

1) Я не буду устанавливать обработчик сигнала до завершения инициализации ttyS.2) Вы не должны вызывать printf() из обработчика сигнала; printf() не является реентерабельным. – wildplasser

+0

Спасибо за ответ, но после ваших комментариев «прерывание» все еще не работает. Есть еще идеи? – gus

ответ

4

Проблема в том, что вы отключите сигналы из дескриптора файла, очистив флаг FASYNC с помощью F_SETFL. Вы должны установить, что если вы хотите получить сигналы:

fcntl(fd, F_SETFL, FNDELAY|FASYNC); 

Кроме того, вы можете использовать имена POSIX для этих флагов (O_NDELAY и O_ASYNC), а не имена BSD для большей мобильности, хотя либо будет работать на Linux.

1

Любые предложения по данной проблеме? Кроме того, как система связывает прерывание с последовательным портом?

Прерывание последовательного порта записывается внутри части устройства последовательного драйвера в ядре linux. Прерывание обрабатывается самим драйвером, поэтому вы не можете контролировать его.

Что делает вышеуказанная программа, уведомляет вас о сигнале, когда инициируется прерывание приема устройства последовательной части.

Вышеупомянутая обработка сигналов не связана с прерываниями, это больше касается обработки. Сначала вы регистрируете свою программу, чтобы получить сигнал при обрыве прерывания io, обработчик сигнала в вашей программе затем отобразит сообщение printf.

Я думаю, что обработка сигнала в вашей программе, не выполняются должным образом Просто исправьте сигнальные части вашей программы

sigset_t mskvar_1     //Variable of signal bitfieldtype 
struct sigaction sigio_action  //Structure which describes signal handler 
void sio_handler(void);    //Signal handler function 

int main() 
{ 
    sigfillset(&mskvar_1);     //set all mask bits of maskbit variable 
    sigprocmask(SIG_SETMASK,&mskvar_1,NULL); //write the mask info present in mskvar_1 to the pd 
    sigdelset(&mskvar_1,SIGIO);    //Unmask SIGIO , to register for IO Interrupt Events 

    sigio_action.sa_handler = sio_handler; //Configure Signal Handler 
    sigio_action.sa_flags = 0; 
    sigfillset(&sigio_action.sa_mask); 
    sigaction(SIGIO,&sigio_action,NULL);  //Install Signal handler 

    // Serial port initializtion here 
    // Set Serial port parameters , Baud Rate and flags 


while(1); 
return 0; 
} 


void sio_handler() 
{ 
    printf("\nSIGIO RECEIVED , I/O interrupt signalled?\n"); 
    return; 
} 
+0

Спасибо за ваш ответ, но сигнал («прерывание») все еще не работает, и я уже проверял, что программа правильно принимает/передает данные через порт. У вас есть другой подход к решению этой проблемы? – gus

6

Я обнаружил, что часть коды отсутствует для исходного кода, чтобы работать ожидается. В приведенном ниже коде работает Linux, скомпилированный с gcc. Добавленная строка кода - это номер, отмеченный /**<<<<<<------This line made it work.**/
Одна строка также была прокомментирована: //baudRate = B115200;.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <fcntl.h> 
#include <sys/signal.h> 
#include <errno.h> 
#include <termios.h> 

void signal_handler_IO (int status); /* definition of signal handler */ 

int n; 
int fd; 
int connected; 
struct termios termAttr; 
struct sigaction saio; 

int main(int argc, char *argv[]) 
{ 
    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); 
    if (fd == -1) 
    { 
     perror("open_port: Unable to open /dev/ttyO1\n"); 
     exit(1); 
    } 

    saio.sa_handler = signal_handler_IO; 
    saio.sa_flags = 0; 
    saio.sa_restorer = NULL; 
    sigaction(SIGIO,&saio,NULL); 

    fcntl(fd, F_SETFL, FNDELAY); 
    fcntl(fd, F_SETOWN, getpid()); 
    fcntl(fd, F_SETFL, O_ASYNC); /**<<<<<<------This line made it work.**/ 

    tcgetattr(fd,&termAttr); 
    //baudRate = B115200;   /* Not needed */ 
    cfsetispeed(&termAttr,B115200); 
    cfsetospeed(&termAttr,B115200); 
    termAttr.c_cflag &= ~PARENB; 
    termAttr.c_cflag &= ~CSTOPB; 
    termAttr.c_cflag &= ~CSIZE; 
    termAttr.c_cflag |= CS8; 
    termAttr.c_cflag |= (CLOCAL | CREAD); 
    termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
    termAttr.c_iflag &= ~(IXON | IXOFF | IXANY); 
    termAttr.c_oflag &= ~OPOST; 
    tcsetattr(fd,TCSANOW,&termAttr); 
    printf("UART1 configured....\n"); 

    connected = 1; 
    while(connected == 1){ 
      // some code 
    } 

    close(fd); 
    exit(0);    
} 

void signal_handler_IO (int status) 
{ 
    printf("received data from UART.\n"); 
} 

Выход из программы был:

./a.out 
UART1 configured.... 
received data from UART. 
received data from UART. 
received data from UART. 
^C 

Я надеюсь, что работает для вас.

+0

Большое спасибо за ответ, теперь это имеет смысл. – gus

 Смежные вопросы

  • Нет связанных вопросов^_^