flush linux OS serial buffer - c

I have a serial program connecting to two devices via two different ports. Whenever I read, of course I have a local buffer with allocated statically with size of packet I am willing to read from serial. My boss, however, noted that storing packets to this local buffer will not be safe, rather he advised to check if I can flush linux OS buffer every time I read from serial. what is your opinion? and how can I do that programatically in ubuntu ?
I think this problem gets solved, if I add TCSAFLUSH to the tcsetattr function. this makes it flush the buffer after all data has been written to serial. this happens just before the next read. hopefully if I usleep() for some time ;)
what if your opinion?

The function you are looking for is tcdrain(fd) or the tcsetattr() option TCSADRAIN.
TCSAFLUSH (and tcflush()) empty the buffer by discarding the data - tcdrain() waits (blocking) until all data has been sent from the buffer:
Line control
...
tcdrain() waits until all output written to the object referred to by fd has been transmitted.
-- man termios
I use the function just before resetting the port options to what they were before I changed them and close the port:
void SerialPort::close() {
if (_fd > -1) {
tcdrain(_fd);
ioctl(_fd, TCSETS2, &_savedOptions);
::close(_fd);
}
_fd = -1;
}

Related

BeagleBone Black UART software FIFO size?

I'm developing a custom application on the BeagleBone Black that has to use the UART capabilities of the device via the Debian Linux that runs on the BBB, for reading big chunks of data. For reading from the UART I'm opening one of the /dev/ttyO0, /dev/ttyO1, etc. devices with the open() function in nonblocking mode. And then I'm trying to read from this port with the read(2) function:
ssize_t read(int fd, void *buf, size_t count);
I would like to know what is the biggest reasonable number for the parameter count and how is it related to the UART's FIFO buffer?
In the AM335x technical reference manual (TI document spruh73p, page 4328, section 19.3.6) I can see that the HW buffer is 64 bytes long. But, as I suspect by using the read() function my program is not communicating directly with the hardware fifo buffer but it is reading from Linux' serial driver's software buffer (if there is such). Is this true? If yes, what is the size of the software fifo? Could somebody please enlighten this field for me?
And then I'm trying to read from this port with the read(2) function
Rather than the "port", you are actually several layers removed from the hardware device, and reading from the system buffer of the serial terminal.
I would like to know what is the biggest reasonable number for the parameter count and how is it related to the UART's FIFO buffer?
First of all the count must be no larger than the user buffer provided.
For a blocking read(), you could probably make this count as large as any buffer you could allocate.
For a nonblocking read(), a count larger than the terminal receive buffer makes little sense.
Note that count is merely a request, and the read() syscall can return with less than the requested number of bytes.
The sizes of the UART FIFO and serial port driver buffers are irrelevant to any read() requests from userspace.
See Linux serial drivers.
... it is reading from Linux' serial driver's software buffer (if there is such). Is this true?
Almost.
The read() syscall from userspace fetches data from the terminal buffer.
The terminal driver is a higher-level driver than the serial port driver.
The terminal buffer has no direct connection to the UART FIFO.
If DMA is employed, then data is transferred from the UART FIFO to a DMA buffer.
If PIO is employed, then data is transferred from the UART FIFO to a driver buffer.
In either case the serial port driver eventually transfers the data to a tty flip buffer.
In non-interrupt mode, data from the tty flip buffer is transferred to the terminal/line-discipline buffer.
Again refer to Linux serial drivers.
If yes, what is the size of the software fifo?
The terminal receive buffer is typically 4096 bytes, although you could write your own line discipline with a different size, or redefine the macro.
From include/linux/tty.h in Linux kernel source:
#define N_TTY_BUF_SIZE 4096
The terminal driver is common to all architectures supported by Linux, so your BBB should have a terminal buffer of 4096 bytes.

Linux C Programming: Concurrent reads/writes to same file descriptor

I am writing a program that interfaces with a particular serial device. The serial device has two channels, and a hardware rx and tx buffer for each channel. Basically, at any given time , you can read/write to either channel on the device.
I am trying to read data from a channel, validate it (and perhaps use some of the data), and then transmit it. Reads are accomplished with iotctl calls to the device, while writes are accomplished with a call to the write() system call.
The main issue I have is with data throughput. I'd like to have an individual thread handle reading and writing for each channel (i.e., a read thread and write thread for each of the two channels). However, I have hit a snag. Everything on the device, from Linux's perspective is accessed via one single device, and I'm not sure that Linux notes that the device has multiple channels.
As a result, currently I open a single file descriptor to the device and perform my reads and writes serially. I'd like to go to the threaded approach, but I'm wondering if concurrent ioctl() and write() calls would cause issues. I understand that read() and write() and not thread safe, but I was wondering if there's any way around that (perhaps calling open() twice, one with read privileges, one with write privileges).
Thanks for your help. Also, I want to avoid having to write my own driver, but that may be an inevitable conclusion...
Also, as a side note, I'm particularly concerned that the device has extremely small hardware buffers. Is there any way to determine how much space the OS uses for a software buffer for data? That is, can I determine whether or not the OS has it's own buffer that is used to prevent overflow of the hardware buffer? The device in question is an I2C UART Bridge.
You can use semaphore to make a mutual exclusion between read/write thread
sem_t sync_rw;
/*init semaphore */
err=sem_init(&sync_rw,0,1); /* shared between thread and initialized with 1 */
if( err != 0 )
{
perror("cannot init semaphore \n");
return -1;
}
in thread write function you do this :
sem_wait(&sync_rw);
write(...)
sem_post(&sync_rw);
same for thread reader :
sem_wait(&sync_rw);
iotctl(...)
sem_post(&sync_rw);
finally :
sem_destroy(&sync_rw);

Socket being busy causes delays in poll()

I'm using a TCP socket to send data from a client. The data is prepared, in advance, so I always have more data to send. Moreover, I can't change the size of the writes, otherwise the server will complain. I do the following:
while (1) {
poll(for POLLOUT condition);
write(to TCP socket);
if (no more data)
break;
}
The problem is that the POLL takes a very long time. I assume this is the time that the socket is actually being written to (or responded to). Is there anyway that I can reduce the amount of time spent in the poll? It is currently a major bottleneck.
Socket being busy causes delays in poll()
Of course it does. That's what poll() is for. To delay until a socket becomes readable or writable.
Your writer is faster than your reader. Look for a solution at the reading end. Your writing end is behaving correctly.
However calling it every time at the head of that loop is pointless. Only call it when you need to know the socket has become writable. It is normally writable all the time, except when your socket send buffer is full, so calling it every time is a waste of time.
Just keep writing until you get EAGAIN/EWOULDBLOCK. Then is the time to call poll(), to tell you when there is space in the socket send buffer. Then just resume writing again as before.
Poll will raise a POLLOUT event when there's enough buffer space to enqueue further data. (Look at this link - Man (7) socket )
If it doesn't, it means write buffer is full and it means you're writing faster than the read capabilities of the other peer. Or simply the network is slower than you expect.

How can I determine the amount of write/output buffer space left on a linux serial port?

You can determine how much data is available to read from a serial port under linux using an ioctl. Is it possible to determine how much buffer space remains for the serial port when writing to it? Effectively I want to write a block of data to a serial port, succeeding only if it can all be offloaded in one go, or failing if it would have to be chunked. The writes and reads to the ports are non-blocking. I'm not expecting this to be the UARTs buffer, but the kernels memory buffer ahead of the UARTs buffer (I guess).
You can determine the amount of write/output.
For read:
ioctl(device_handler, TIOCINQ, &bytes);
For write:
ioctl(device_handler, TIOCOUTQ, &bytes);
Size of FIFO buffer:
serial_struct serinfo;
memset(&serinfo, 0, sizeof(serinfo));
ioctl(device_handler, TIOCGSERIAL, &serinfo);
serinfo.xmit_fifo_size;
Regards,
VA.
The serial port is a character device not a block device. It has no buffer.
Character devices ( such as Serial port, keyboard, mouse) only writes and reads a character not a word.
For exame if you listen to a serial someone writes " have a nice day ", if you do not listen from the time he starts typing, you would not see the entire phrase. You would see only the characters typed when you listen
If you access serial port using file descriptor, you can use select for checking whenever the descriptor is ready for non-blocking write. I don't know whenever this works for serial ports. I used this for TCP sockets and it worked.

Flush communications handle receive buffer?

In Win32 C is there an API call to flush (dump) the contents of a COM port recieve buffer? I could only find functions to flush the transmit buffers.
`PurgeComm()' can drop all characters in either or both the Tx and Rx buffers, and abort any pending read and/or write operations on the port. To do everything to a port, say something like:
PurgeComm(hPort, PURGE_RXABORT|PURGE_TXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR)
You may also want to make sure that you've handled or explicitly ignored any pending errors on the port as well, probably with ClearCommError().
ReadFile() can be used to empty just the Rx buffer and FIFO by reading all available bytes into a waste buffer. Note that you might need to have "unnatural" knowledge in order to size that buffer correctly, or repeat the ReadFile() call until it has no more to say.
However, reading the buffer to flush it will only make sense if you have the COMMTIMEOUTS set "rationally" first or the read will block until the buffer is filled.
flushing a receive buffer doesn't make sense, to get data out of a com port receive buffer just call ReadFile on the handle to the com port
FlushFileBuffers synchronously forces the transmission of data in the transmit buffers
PurgeComm empties the buffer without transmission or reception (its a delete basically)

Resources