RXTX Loopback Test Program(1) Filed under: java — Tags: java, java-serial-port — kunilkuda @ 11:36 am One comment that I had in this site said that the RXTX library is not very reliable in the receiving part (using data available event). Finding the address of a control register for a serial port in Ubuntu (or UBOOT). I understand that there are two ways to test the internal loopback 1) You can Configure the UART to act as an internal Loopback 2) You can get the Transceiver to act as a loopback. Forward shell to serial on Linux. PPP connection to a virtualbox guest. I want to perfrom loopback test on serial port using a loopback connector. I need to write a code using qt 4.7.4. But I am totally new to serial port programming. DB9 & DB25 D-type connector pin connections for an RS232 serial loopback test. RS232 basics RS232 standard Software handshaking Signals & voltage levels Pinouts & connectors Loopback connections RS232. The connections for the serial loopback connector are given below in tabular form for a DB-9 D-type connector using the common pinout. On Linux and OSX: minicom is the preferred way to perform loopback test on Raspberry Pi and other *-nix systems. Running the Test Testing Serial Port of Raspberry Pi: As shown in the figure below.
I have a serial device set up as loopback (meaning it will simply echo back any character it receives), and I'd like to measure effective throughput speed. For this, I hoped I could use time
, as in
Loopback Test Software
where '...
' would be some command I could run.
Now, the first problem is that I want to use the device at 2000000 bps, so I cannot use ttylog or screen (they both seem to go up to 115200 bps only). However, working with /dev/ttyUSB0
as a file (using file redirection and cat
) seems to work fine:
Now, I'd like to do something similar - I'd like to cat
a file to a serial port, and have the serial port read back - but from a single terminal command (so I could use it as argument to time
).
I thought that I could use a Bash process substitution, to have the 'writing' and 'reading' part go, sort of, in 'parallel' - if I try it with named pipes, it works:
Up there, I'm not using comm
for any other purpose, than to (sort of) merge the two processes into a single command (I guess, I could have just as well used echo
instead).
Unfortunately, that trick does not seem to work with a serial port, because when I try it, I sometimes get:
..., however, usually I just get no output whatsoever. This tells me that: either there is no control of which process starts first, and so cat
may start reading before the port is ready (however, that doesn't seem to be a problem in the first example above); or in Linux/Bash, you cannot both read and write to a serial port at the same time, and so the 'Invalid argument
' would occur in those moments when both read and write seem to happen at the same time.
So my questions are:
- Is there a way to do something like this (
cat
a file to a serial port configured as loopback; read it back and see how long it takes) only in Bash, without resorting to writing a dedicated C program? - If I need a dedicated C program, any source examples out there on the net I could use?
Thanks a lot for any responses,
Cheers!
EDIT: I am aware that the while
loop written above does not exit; that command line was for preliminary testing, and I interrupt it using Ctrl-C. ( I could in principle interrupt it with something like timeout -9 0.1 bash -c 'while (true) do echo AA ; done'
, but that would defeat the purpose of time
, then :) )
The reason that while
is there, is that for the time being, reading via cat
from the device exits immediately; at times, I have set up the device, so that when cat
is issued, it in fact blocks and waits for incoming data; but I cannot as of yet figure what's going on (and partially that is why I'm looking for a way to test from the command line).
In case I didn't use the while
, I imagine for timing, I'd use something like:
time bash -c 'comm <(echo '1234567890' > /dev/ttyUSB0) <(cat -A /dev/ttyUSB0)'
... however for this to be working, sort of, assumes that cat -A /dev/ttyUSB0
starts first and blocks; then the echo
writes to the serial port (and exits); and then cat -A
outputs whatever it read from the serial port - and then exits. (And I'm not really sure neither if a serial port can behave this way at all, nor if cat
can be made to block and exit arbitrarily like that).
The exact method really doesn't matter; if at all possible, I'd just like to avoid coding my own C program to do this kind of testing - which is why my primary interest is if it is somehow possible to run such a 'full-duplex test' using basic Bash/Linux (i.e. coreutils
); (and if not, if there is a ready-made code I can use for something like this).
EDIT2: Also possibly relevant:
dsolimano2 Answers
Well, here is something like a partial answer - although the question about the use of bash is still open. I tried to look a little bit in some C code solutions - and that, it seems, isn't trivial either! :)
First, let's see what possibly doesn't work for this case - below is an example from 'between write and read:serial port. - C':
Linux Serial Loopback Test Program Free
The problem with the above code is that it doesn't explicitly initialize the serial port for character ('raw') operation; so depending on how the port was set previously, a session may look like this:
... in other words, there is no echoing of the input data. However, if the serial port is set up properly, we can get a session like:
... (but even then, this sertest
code fails on input words greater than 3 characters.)
Finally, through some online digging, I managed to find '(SOLVED) Serial Programming, Write-Read Issue', which offers a writeread.cpp
example. However, for this byte-by-byte 'duplex' case, not even that was enough - namely, 'Serial Programming HOWTO' notes: 'Canonical Input Processing ... is the normal processing mode for terminals ... which means that a read will only return a full line of input. A line is by default terminated by a NL (ASCII LF) ...' ; and thus we have to explicitly set the serial port to 'non-canonical' (or 'raw') mode in our code via ICANON
(in other words, just setting O_NONBLOCK
via open
is not enough) - an example for that is given at '3.2 How can I read single characters from the terminal? - Unix Programming Frequently Asked Questions - 3. Terminal I/O'. Once that is done, calling writeread
will 'correctly' set the serial port for the serport
example (above), as well.
So I changed some of that writeread
code back to C, added the needed initialization stuff, as well as time measurement, possibility to send strings or files, and additional output stream (for 'piping' the read serial data to a separate file). The code is below as writeread.c
and serial.h
, and with it, I can do something like in the following Bash session:
Well:
- First surprise - it goes faster if I'm writing to a file, than if I'm piping to
/dev/null
! - Also, getting around 1000 Bps - whereas the device is apparently set for 200000 BPS!!
At this point, I'm thinking that the slowdown is because after each written byte in writeread.c
, we wait for a flag to be cleared by the read interrupt, before we proceed to read the serial buffer. Possibly, if the reading and writing were separate threads, then both reading and writing could try to use bigger blocks of bytes in single read
or write
calls, and so bandwidth would be used better ?! (Or, maybe the interrupt handler does act, in some sense, like a 'thread' running in parallel - so maybe something similar could be achieved by moving all read related functions to the interrupt handler ?!)
Ah well - at this point, I am very open to suggestions / links for existing code like writeread.c
, but multithreaded :) And, of course, for any other possible Linux tools, or possibly Bash methods (although it seems Bash will not be able to exert this kind of control...)
Cheers!
writeread.c:
serial.h:
sdaausdaauWell, I managed to put writeread.c
in a threaded version using pthread
(code is below - I don't think serial.h
changed much; it's not used that much in the threaded version anyways). I have also lowered the speed to 115200, and now I can confirm these measurements with the device, in the sample command line session below:
Well, measurements now report up to 99% of the expected baud rate, so I guess that means that the profiling aspect of this program should work. Notice:
- For this device, the
write
is executed in a single chunk (as the PC should be able to handle the sequencing to packets, if necessary), - while the
read
goes on in smaller chunks (probably indicating that the device doesn't wait for the entire chunk to arrive - instead it starts sending back smaller chunks as soon as it has received enough)
Well, I guess this is what I needed originally; I also guess it is probably not possible to arrange cat
and echo
via process substitution to execute in this, let's call it 'threaded', manner :) (Now, I do have a problem with doing the same at 2000000 baud, but that indicates a problem with the programming of the device).
Cheers!
writeread.c - threaded version
sdaausdaau