I seem to be having a mental block, about getting serial I/O to work under FreeBSD. Usually, this kind of stuff is really easy, but I'm doing something wrong.
My end goal is to connect a home automation system (UPB) to my FreeBSD server. That is done via a 4800 baud serial line, using only four wires (ground, TD, RD, and DTR, which the UPB gadget only needs to suck power from). I know the hardware works: I can speak to the UPB gadget using Windows (running in a VMware VM on my Mac), and I can even talk to it "directly" (without software, with just a terminal emulator) using HyperTerminal on Windows. So I connect it to the serial port on my FreeBSD server, and try using
Time to simplify: I simply replaced the hardware device with a loopback adapter, which bridges pins 2 and 3 (TD and RD). I expect to see every character I type to be echoed to the screen. Now comes the amazing part: it still doesn't work, nothing happens! This is stupid, talking to a loopback wire simply has to work. So I decided to instead try it on my Mac using the console, and the exact same hardware that worked under Windows (remember, Windows was in a VM on the Mac), and lo and behold,
EDIT: See message from 20130109 below; it works fine under MacOS, if you just install the correct driver.
Here are the details. The server in question is vanilla PC hardware, an Intel AtomMoBo motherboard with two serial ports:
Output from cu, before running
Here is the output from stty while cu is running (just to show you that the serial line discipline is still set reasonably, look at clonal and crtscts), collected from a separate terminal window:
I have a display box on the serial port, and it shows the following: When
And here is another weirdness: suspecting that hardware flow control may be on after all, I also bridged pins 4 and 5 (CTS and RTS) and pins 6/8/20 (DTR, DSR and CD). Then I decided to suspect
Note that it claims that CTS, DSR and CD are all inactive, even though CTS is connected to RTS, and DSR/CD are connected to DTR, and with the LEDs on the breakout box I can clearly see that they are all active.
Two more things I checked: The results on both serial ports cuau0 and cuau1 are exactly the same. As is the behavior on my Mac (using a no-name brand USB serial adapter, which works fine when running Windows in a VM on that very same Mac).
What gives? Have I completely forgotten how to use serial I/O on BSD-like operating systems? What am I doing wrong?
My end goal is to connect a home automation system (UPB) to my FreeBSD server. That is done via a 4800 baud serial line, using only four wires (ground, TD, RD, and DTR, which the UPB gadget only needs to suck power from). I know the hardware works: I can speak to the UPB gadget using Windows (running in a VMware VM on my Mac), and I can even talk to it "directly" (without software, with just a terminal emulator) using HyperTerminal on Windows. So I connect it to the serial port on my FreeBSD server, and try using
cu
to talk to it, and it doesn't work at all: no bytes going in or out.Time to simplify: I simply replaced the hardware device with a loopback adapter, which bridges pins 2 and 3 (TD and RD). I expect to see every character I type to be echoed to the screen. Now comes the amazing part: it still doesn't work, nothing happens! This is stupid, talking to a loopback wire simply has to work. So I decided to instead try it on my Mac using the console, and the exact same hardware that worked under Windows (remember, Windows was in a VM on the Mac), and lo and behold,
cu
doesn't work there either. So it seems that I have some mental block about using serial I/O on FreeBSD (and friends, after all the Mac is a close relative).EDIT: See message from 20130109 below; it works fine under MacOS, if you just install the correct driver.
Here are the details. The server in question is vanilla PC hardware, an Intel Atom
Code:
# uname -a
FreeBSD house.lr.los-gatos.ca.us 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:15:25 UTC 2012 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
# dmesg | egrep "uart|sio|tty|cua"
uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
uart1: <16550 or compatible> port 0x2f8-0x2ff irq 3 on acpi0
Output from cu, before running
cu
, the cu command line, and the cu variables:
Code:
# stty -a -f /dev/cuau1
speed 9600 baud; 0 rows; 0 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
brkint -inpck -ignpar -parmrk
oflags: opost onlcr -ocrnl tab0 -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
# cu -s 4800 -l /dev/cuau1 dir
Connected
~v
beautify true
baudrate 4800
dialtimeout 60
eofread
eofwrite
eol
escape ~
exceptions
force \^P
framesize 1024
host cu4800
log /var/log/aculog
phones
prompt \^J
raise false
raisechar \^@
record
remote
script false
tabexpand false
verbose false
SHELL /bin/ksh
HOME /root
echocheck false
disconnect
tandem true
linedelay 0
chardelay 0
etimeout 0
rawftp false
halfduplex false
localecho false
parity none
hardwareflow false
linedisc 0
direct true
Here is the output from stty while cu is running (just to show you that the serial line discipline is still set reasonably, look at clonal and crtscts), collected from a separate terminal window:
Code:
# stty -a -f /dev/cuau1
speed 4800 baud; 0 rows; 0 columns;
lflags: -icanon -isig -iexten -echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
-extproc
iflags: -istrip -icrnl -inlcr -igncr ixon ixoff ixany imaxbel -ignbrk
brkint -inpck -ignpar -parmrk
oflags: -opost onlcr -ocrnl tab0 -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
I have a display box on the serial port, and it shows the following: When
cu
starts, it correctly turns on DTR and RTS, but it never transmits anything on TD. Note that the serial line is set for no hardware flow control. Using "~#" in cu, I can transmit a break, and that actually makes the TD line toggle correctly. I have verified with a probe that nothing is being transmitted out the transmit pin.And here is another weirdness: suspecting that hardware flow control may be on after all, I also bridged pins 4 and 5 (CTS and RTS) and pins 6/8/20 (DTR, DSR and CD). Then I decided to suspect
cu
, and tried minicom.py
, which is an example program that comes with the python serial package. It has the nice feature that one can toggle RTS and DTR under keyboard control. The funky thing is the following in its output (as a response to Ctrl-T Ctrl-I to give information):
Code:
# miniterm.py /dev/cuau0 4800
--- Miniterm on /dev/cuau0: 4800,8,N,1 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
--- Settings: /dev/cuau0 4800,8,N,1
--- RTS: active DTR: active BREAK: inactive
--- CTS: inactive DSR: inactive RI: inactive CD: inactive
--- software flow control: inactive
--- hardware flow control: inactive
--- data escaping: raw linefeed: CR/LF
Two more things I checked: The results on both serial ports cuau0 and cuau1 are exactly the same. As is the behavior on my Mac (using a no-name brand USB serial adapter, which works fine when running Windows in a VM on that very same Mac).
What gives? Have I completely forgotten how to use serial I/O on BSD-like operating systems? What am I doing wrong?