Scheduled Maintenance: We are aware of an issue with Google, AOL, and Yahoo services as email providers which are blocking new registrations. We are trying to fix the issue and we have several internal and external support tickets in process to resolve the issue. Please see: viewtopic.php?t=158230

 

 

 

Serial port signal(IRQ) handler

Programming languages, Coding, Executables, Package Creation, and Scripting.
Post Reply
Message
Author
Lauris_k
Posts: 4
Joined: 2014-11-25 12:19

Serial port signal(IRQ) handler

#1 Post by Lauris_k »

Hello,

I'm writing some serial(UART) handler but have stuck on few issues, maybe anyone can help to show me what I'm doing wrong.
Basically I'm intending to write serial RX signal handler.
Application receives defined packages of data over serial which contains header and payload. Handler should analyse incoming stream and upon detection of header (header is 6B in length) switches to receive payload of length defined in header, then after receiving full message packs it and sends to application for handling.
Problem I'm facing is that at random moments in signal I receive errors that "Resource temporarily unavailable" while reading from ttyOx device and I see that sometimes I miss incoming data.
Also is it possible that if while I'm handling signal one more signal arrives and it is started to be handled parallel? If it is, what are the ways to prevent it? So I would be sure that no more signals will fire on same peripheral until I will finish handling what I have on my hands now.

Serial open and init:

Code: Select all

int open_port(int port_nr) {
    int fd; /* File descriptor for the port */
    switch (port_nr) {
    case 1:
        fd = open("/dev/ttyO1", O_RDWR | O_NOCTTY | O_NDELAY); 
        break;
    case 2:
        fd = open("/dev/ttyO2", O_RDWR | O_NOCTTY | O_NDELAY); 
        break;
    default:
        printf("Invalid Serial port selected\n");
        return (-1);
    }
    if (fd == -1) {
                /* Could not open the port.*/
        perror("open_port Failed - ");
    } else {
        switch (port_nr) {
        case 1:
            sig_act.sa_handler = ttyO1_signal_handler_IO;
            UART_port_ttyO1 = fd;
            ttyO1_TX_list = NULL;
            if (pltfrm_mbx_init(&ttyO1_Mbx, sizeof(sPubMsg), 20) < 0) {
              printf("failed to create mailbox !! \n");
              return (-1);
            }
            break;
        case 2:
            sig_act.sa_handler = ttyO2_signal_handler_IO;
            UART_port_ttyO2 = fd;
            ttyO2_TX_list = NULL;
            if (pltfrm_mbx_init(&ttyO2_Mbx, sizeof(sPubMsg), 20) < 0) {
              printf("failed to create mailbox !! \n");
              return (-1);
            }
            break;
        default:
            printf("Invalid Serial port selected\n");
            return (-1);
        }
        sig_act.sa_flags = 0;
        sig_act.sa_restorer = NULL; 
        sigaction(SIGPOLL, &sig_act, NULL);
        fcntl(fd, F_SETFL, (FNDELAY | FASYNC));
        fcntl(fd, F_SETOWN, getpid());
    }
    return (fd);
}

void setup_port(int port_nr) {
    struct termios  options;
    int             port = port_nr_to_fd(port_nr);
    if (port < 0) {
        printf("Request to set-up invalid port(%d) detected...\n", port_nr);
    }
            /* get the current options */
    tcgetattr(port, &options);
            /* Set the to 57600kbps baud rate 8N1*/
    cfsetispeed(&options, B57600);
    cfsetospeed(&options, B57600);
    options.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
    options.c_cflag |= CS8;    /* Select 8 data bits */
    options.c_cflag     |= (CLOCAL | CREAD);
    options.c_lflag     &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_oflag     &= ~OPOST;
    options.c_iflag     &= ~(IXOFF | IXON);
    options.c_cc[VMIN]  = 0;
    options.c_cc[VTIME] = 0;
            /* set the options */
    tcsetattr(port, TCSANOW, &options);
}
Signal handler basics:

Code: Select all

static int rd_serial(int port, uint8_t *buff, int len) {
    int res;
    res = read(port, buff, len); 
    if (res == -1) {
        perror("serial_read: Failed to read /dev/ttyO2 - ");
    } 
    return res;
}

static int handle_RX_payload(int port, sMsgData *RX_msg) {
***
    rd_serial(port, pnt, (RX_msg->message_len - rx_len));
***
}

static int handle_RX_header(int port, sMsgData *RX_msg) {
    static uint8_t  header[6];
    uint8_t         byte;
    int             rx_cnt;
    do {
        rx_cnt = rd_serial(port, &byte, 1);
        if (rx_cnt > 0) {
            memcpy(header, &header[1], 5);
            header[5] = byte; 
            RX_msg->mesage_type = check_header(header);
            if (RX_msg->mesage_type != 0xFF) {  //valid header sequence found
                RX_msg->message_len = (header[3] << 8) + header[2] - 4; 
                RX_msg->payload = (uint8_t*)malloc(RX_msg->message_len);
                return STAGE_COMPLETED;
            }
        }
    } while (rx_cnt > 0); 
    return EMPTY_BUFFER;
}

static uint8_t signal_handler_IO (int port, uint8_t *rx_state, sMsgData *RX_msg) {
    uint8_t   *state = rx_state;
    int       res;
***
    res = handle_RX_header(port, RX_msg);
***
    res = handle_RX_payload(port, RX_msg);
***
}

void ttyO1_signal_handler_IO (int status) {
    static uint8_t  state = 2;
    static sMsgData ttyO1_RX_msg;
    signal_handler_IO(UART_port_ttyO1, &state, &ttyO1_RX_msg);
}

void ttyO2_signal_handler_IO (int status) {
    static uint8_t  state = 2;
    static sMsgData ttyO2_RX_msg;
    signal_handler_IO(UART_port_ttyO2, &state, &ttyO2_RX_msg);
}
Error I see in my log:

Code: Select all

serial_read: Failed to read /dev/ttyO2 - : Resource temporarily unavailable

BowCatShot
Posts: 959
Joined: 2006-07-15 12:08

Re: Serial port signal(IRQ) handler

#2 Post by BowCatShot »

Are you really connecting through a usb port rather than a serial port? If so check to see if linux is sharing that usb with another. In my case the usb that I was trying to communicate over was being shared with the one used by the mouse. Switching to another machine solved the problem.

tomazzi
Posts: 730
Joined: 2013-08-02 21:33

Re: Serial port signal(IRQ) handler

#3 Post by tomazzi »

I think that the problem is in signal handler routine.
You should *never* try to perform any I/O operations in a signal handler, including asynchronous access - the result of such operation is undefined.

The correct way is to create some process or better thread waiting on some semaphore or spinlock, and trigger it from the sig handler.

Regards.
Odi profanum vulgus

Lauris_k
Posts: 4
Joined: 2014-11-25 12:19

Re: Serial port signal(IRQ) handler

#4 Post by Lauris_k »

BowCatShot wrote:Are you really connecting through a usb port rather than a serial port? If so check to see if linux is sharing that usb with another. In my case the usb that I was trying to communicate over was being shared with the one used by the mouse. Switching to another machine solved the problem.
Nop. It's serial, to be exact its Uart port on BeagleBone black. Tho some signal mixing happens, but that issue now isn't such important, basically I get gets() /*from command line*/ triggered in case of RX on ttyO2.
tomazzi wrote:I think that the problem is in signal handler routine.
You should *never* try to perform any I/O operations in a signal handler, including asynchronous access - the result of such operation is undefined.

The correct way is to create some process or better thread waiting on some semaphore or spinlock, and trigger it from the sig handler.

Regards.
You mean avoid any read() while in signal?
Anyway thank you for concept, that makes more sense that what I did.
Other question is - do I get signal from any incoming char on serial, or it is not related to bytes received, but buffer to buffer operation and RX timeout?

tomazzi
Posts: 730
Joined: 2013-08-02 21:33

Re: Serial port signal(IRQ) handler

#5 Post by tomazzi »

I think You should read this first (and maybe other related topics):
http://stackoverflow.com/questions/1013 ... sigio-in-l

Also, You should check for EAGAIN, which can be returned by read() in O_NONBLOCK mode.

Regards.
Odi profanum vulgus

Lauris_k
Posts: 4
Joined: 2014-11-25 12:19

Re: Serial port signal(IRQ) handler

#6 Post by Lauris_k »

tomazzi wrote:I think You should read this first (and maybe other related topics):
http://stackoverflow.com/questions/1013 ... sigio-in-l

Also, You should check for EAGAIN, which can be returned by read() in O_NONBLOCK mode.

Regards.
I have read that topic and quite a lot of others, that's how I came up to point where I'm now (sorry this is basically start of my programming in unix, and it does have some differences from win C/C++ and especially embedded C, mostly in parts of multitasking(multithreading) and need to edit data on incoming stream).

and for modifying incoming stream I found that these flags should solve my issues:

Code: Select all

raw same as -ignbrk -brkint -ignpar -parmrk  -inpck  -istrip  -inlcr
              -igncr  -icrnl   -ixon   -ixoff   -iuclc  -ixany -imaxbel -opost
              -isig -icanon
Tho probably reworking signal handler most likely is unavoidable.

Post Reply