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.
Related
My question regards <termios.h>. As I understand, two buffers exist in reading something over a UART - a hardware buffer where received bytes are stored, and a software buffer where we load the stuff that has been stored in the hardware buffer. This software buffer is the second argument in read(uart_channel, BUFFER, length) as I understand.
Please explain: how long is the hardware buffer? Do I have control over how long it is? For me it is critical to read the 12 most recent bytes sent over UART by a device - how can I ensure this?
I had a similar situation once and what I did is to create a thread that kept on reading the UART (blocking read) and I used a FIFO between the threads.
If you cannot use threading, you might just use select.
Most uC I've seen have a hardware FIFO that can be set to interrupt after, say [1,2,4,8,16] bytes. If the FIFO is left 'partially full' for some small multiple of the character interval for the currently configured baud rate, the UART interrupts anyway. If you really must have access to bytes ASAP, then you need to set the FIFO 'length' to 1. Of course, your driver should do that when initializing the UART.
Failing that, I guess you could poll it:(
I'm programming for device on sh4-arch linux 2.6.32 who plays video stream from UDP socket.
I've got a ring buffer in user space (called ubuffer) which decoder (kernel space) reads. ubuffer was mapped from kernel space buffer (called kbuffer).
Existing application (with source code) reads data from UDP socket to ubuffer in user space. For decreasing of delay, I've made a driver who reads payload data from UDP sk_buf directly to ring buffer. Right now I'm using ioctl from existing app, who sends an ubuffer to ioctl_proc for every UDP packet. ioctl_proc making copy_to_user(ubuffer+off, skb->data+skb_off, len) and all works fine. I need to make it without any userspace app and ioctl. So I've send kbuffer to my driver and make memcpy(kbuffer+off, skb->data+skb_off, len) instead of copy_to_user (that's the only difference) with the same parameters and it not works: I'm see the picture with 10% of valid pixel (some text and colors), but rest are fails. If kbuffer was wrong, I'll shall not see anything right, but I see something.
Value of len is about 100-1300 bytes.
What I'm doing wrong? Maybe I must to use some page-aligned calls?
I am working with serial port programming and i have following doubt please clear it
Does Read/Write system call reads and writes data directly from/to UART buffer?
Which buffer does Rx and Tx of "/proc/tty/driver/serial" refers to.
Please clarify.
read()and write() access data via a so called file-descriptor return by a call to open().
open() gets passed in the name of a serial device.
Serial devices could be named "/dev/ttySX" with X={0..N}.
Why are you worried about:
Does Read/Write system call reads and writes data directly from/to
UART buffer?
The kernel takes care of the actual read/write calls to a file regardless if its a device or a data file, in the case of device, IOCTL calls will be made to the device in question and handle it behind the scenes.
Which buffer does Rx and Tx of "/proc/tty/driver/serial" refers to.
Again, that is handled by the kernel and related IOCTL calls to the serial driver by way of device descriptor to the actual serial port.
If still in doubt, a refresher on serial port programming under Un*x environments such as Linux/FreeBSD would be recommended.
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;
}
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.