2

I have a problem with my uart read (on raspberry pi). It works ok but it stops in a loop and waits on data... I made an option O_NDELAY but is stops even so.

I use two terminal windows:

  • one is used for uart program
  • on the second i write:

    echo '123445' > /dev/ttyAMA0 (raspberry Pi uart port)

Complete code is below.

#include <stdio.h>
#include <unistd.h>             //Used for UART
#include <fcntl.h>              //Used for UART
#include <termios.h>        //Used for UART


int main(int argv, char * argc[])
{
// Setting Up The UART

    //-------------------------
    //----- SETUP USART 0 -----
    //-------------------------
    //At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie         the alt0 function) respectively
    int uart0_filestream = -1;

    //OPEN THE UART
    //The flags (defined in fcntl.h):
    //  Access modes (use 1 of these):
    //      O_RDONLY - Open for reading only.
    //      O_RDWR - Open for reading and writing.
    //      O_WRONLY - Open for writing only.
    //
    //  O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
    //                                          if there is no input immediately available (instead of blocking). Likewise, write requests can also return
    //                                          immediately with a failure status if the output can't be written immediately.
    //
    //  O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.


    uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);      //Open in non blocking read/write mode
    if (uart0_filestream == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
        printf("Error - Unable to open UART.  Ensure it is not in use by another application\n");
    }

    //CONFIGURE THE UART
    //The flags (defined in termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
    //  Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
    //  CSIZE:- CS5, CS6, CS7, CS8
    //  CLOCAL - Ignore modem status lines
    //  CREAD - Enable receiver
    //  IGNPAR = Ignore characters with parity errors
    //  ICRNL - Map CR to NL on input
    //  PARENB - Parity enable
    //  PARODD - Odd parity (else even)
    struct termios cfg;

  //get existing configuration setup
  tcgetattr(uart0_filestream, &cfg);

  //fcntl(deviceFD, F_SETFL, FNDELAY);
  fcntl(uart0_filestream, F_SETFL, 0);

  ////set both incoming and outgoing baud rates...
  cfsetispeed(&cfg, B115200);
  cfsetospeed(&cfg, B115200);

  cfg.c_cflag |= (CLOCAL | CREAD);

  ////8N1 (8 data bits, No parity, 1 stop bit)
  cfg.c_cflag &= ~PARENB;
  cfg.c_cflag &= ~CSTOPB;
  cfg.c_cflag &= ~CSIZE;
  cfg.c_cflag |= CS8;

  cfg.c_cflag &= ~CRTSCTS;  //~CNEW_RTSCTS; //disable hardware flow control

  //use RAW unbuffered data mode (eg, not canonical mode)
  cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IGNBRK);

  cfg.c_iflag &= ~(IGNPAR | IXON | IXOFF | IXANY);

  //raw (unprocessed) output mode
  cfg.c_oflag &= ~OPOST;

  tcsetattr(uart0_filestream, TCSANOW, &cfg);

    //Transmitting Bytes

    //----- TX BYTES -----
    unsigned char tx_buffer[20];
    unsigned char *p_tx_buffer;

    p_tx_buffer = &tx_buffer[0];
    *p_tx_buffer++ = 'H';
    *p_tx_buffer++ = 'e';
    *p_tx_buffer++ = 'l';
    *p_tx_buffer++ = 'l';
    *p_tx_buffer++ = 'o';

    if (uart0_filestream != -1)
    {
        int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0]));      //Filestream, bytes to write, number of bytes to write
        if (count < 0)
        {
            printf("UART TX error\n");
        }
    }
    //Receiving Bytes

    //----- CHECK FOR ANY RX BYTES -----
    while(1) {

    printf("loop\n");

    if (uart0_filestream != -1)
    {
        // Read up to 255 characters from the port if they are there
        unsigned char rx_buffer[256];
        int rx_length = read(uart0_filestream, (void*)rx_buffer, 255);      //Filestream, buffer to store in, number of bytes to read (max)


        if (rx_length < 0)
        {
            //An error occured
            printf("UART RX error\n");
        }
        else if (rx_length == 0)
        {
            //No data waiting
          printf("no data UART RX   test commit\n");
        }
        else
        {
            //Bytes received
            rx_buffer[rx_length] = '\0';
            printf("%i bytes read : %s\n", rx_length, rx_buffer);
            //break;
        }
    }
    sleep(1);
}
//Closing the UART if no longer needed

    //----- CLOSE THE UART -----
    close(uart0_filestream);

  return 0;
}
uvesten
  • 3,365
  • 2
  • 27
  • 40
szymon hrapkowicz
  • 133
  • 3
  • 3
  • 9

2 Answers2

2

I used to have the same problem, and problem is not related with code and solution is just disable login on serial port, there is a file at /etc/inittab open this file with nano and find this line:

 T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

and put a # char at begining this line than save and reboot and it is working weirdly.

flo
  • 9,713
  • 6
  • 25
  • 41
0

You can use O_NONBLOCK flag to make the read/write operation non blocking.

Chirag Desai
  • 1,249
  • 1
  • 10
  • 22
  • i made my program with those two O_NDELAY / O_NONBLOCK but it's not working. the solution with SIGNAL works http://stackoverflow.com/questions/15119412/setting-serial-port-interruption-in-linux/15455672#15455672 – szymon hrapkowicz May 21 '13 at 06:46
  • 1
    Signal in read is used as the read is blocking operation in linux, it will not return though the underlying serial port is closed. We have two options in this case either we use `signals` or we use `select` operation. But I thought your aim is to use non blocking read and hence I did not recommend select to use :) – Chirag Desai May 21 '13 at 06:57