Home Reading file descriptor blocks in Linux
Reply: 0

Reading file descriptor blocks in Linux

user4784
1#
user4784 Published in June 20, 2018, 1:18 am

This is a continuation of a previous question: Problems reading and writing to the same file descriptor in Linux but many changes have been made.

The project is Debian Linux running on a single board computer. The main program is a webserver (using the libwebsockets library) with motor control and GPS plugins. My question involves reading bytes from a file descriptor in the motor control code which is in C.

The fd is read/write and the read and write functions are each running on their own thread. A packet consists of 19 bytes and the write function is working.

Init port call:

    mc_fd = InitPort("/dev/ttyS1", "COM2", O_RDWR, B115200);

Code for opening port/fd:

int InitPort( char *port, char *name, int oflags, speed_t baudRate ) {

    int fd, rg, rs;                                 // File descriptor
    fd = open(port, oflags);                // Open the port like a file
    assert(fd > 0);                         // Open returns -1 on error

    struct termios options;                 // Initialize a termios struct
    rg = tcgetattr(fd, &options);               // Populate with current attributes
    if( rg < 0 ) {
        printf("Failed to get attr: %d, %s\n", fd, strerror(errno));
    }
    cfsetospeed (&options, baudRate);       // Set baud rate out
    cfsetispeed (&options, baudRate);       // Set baud rate in (same as baud rate out)

    options.c_cflag &= ~CSIZE;              // Clear bit-length flag so it can be set
        //8N1 Serial Mode
        options.c_cflag &= ~CSTOPB;         // Set stop bit:        1
        options.c_cflag &= ~CRTSCTS;        // Set flow control:    none

    options.c_cc[VMIN]  = 1;
    options.c_cc[VTIME] = 2;
    cfmakeraw(&options);
    options.c_cflag |= (CLOCAL | CREAD);    // Enable receiver, and set local mode
    rs = tcsetattr(fd, TCSANOW, &options);      // Set new attributes to hardware
    if( rs < 0 ) {
        printf("Failed to set attr: %d, %s\n", fd, strerror(errno));
    }
    return fd;
}

The read function identifies the packet by header characters (0xA552) and then stuffs bytes into an array to receive the 16-byte body of the packet.

Receive function:

void *ReceiveMotorPacket( void *arg )
{
    // Receive 16 byte packet for status, control, and motor position:
    //  [0] command1
    //  [2] status1
    //  [4] motor1Pos
    //  [8] command2
    // [10] status2
    // [12] motor2Pos

    int checksum, idx;
    receiveState = MOTOR_HEAD_1;

    while( 1 ) {

        // receive byte from motor
        read( mc_fd, incomingByte, 1 );

        inChar = *incomingByte;

        // FSM to receive packet
        switch( receiveState ) {

            case MOTOR_HEAD_1:
                if( inChar == 0xA5 ) {
                    receiveState = MOTOR_HEAD_2;
                    checksum = 0;
                }
                break;

            case MOTOR_HEAD_2:
                if( inChar == 0x52 ) {
                    receiveState = MOTOR_DATA;
                    char idx = 0;
                    checksum = 0xA5 + 0x52;
                } else {        printf
                    receiveState = MOTOR_HEAD_1;
                }
                break;

            case MOTOR_DATA:
                readPacket[idx++] = inChar;
                checksum += inChar;
                if( idx >= 17 ) {
                    receiveState = MOTOR_CHECKSUM;
                }
                break;

            case MOTOR_CHECKSUM:
                if( checksum == inChar ) {

                    printf("readPacket = %016X\n", readPacket);

                    // Check status bits and set global variables
                    mc.az_status    = *( signed short * )&readPacket[2];
                    mc.el_status    = *( signed short * )&readPacket[10];

                    // If motor is disabled, set global variable for feedback to GUI
                    if( !az.enable ) {
                        mc.az_position  = *( signed int   * )&readPacket[4];
                    }

                    if( !el.enable ) {
                        mc.el_position  = *( signed int   * )&readPacket[12];
                    }

                    receiveState = MOTOR_HEAD_1;

                } else {
                    printf("checksum error!\n");
                    receiveState = MOTOR_HEAD_1;
    }
                break;

            default:

                break;
            }
        }
    }

I am unable to receive any characters and the read() just blocks the operation of the receive thread. The rest of the program executes normally.

Thank you for your input.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.317952 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO