sercat
Problem
Often it is necessary to cat data from serial port to another process.
This is hindered by the sometimes cumbersome setting of speeds.
With embedded platforms (Arduino, ESP8266, ...) there is a further problem with the DTR and RTS lines;
these can be set for various purposes that interfere with the communication.
By default, both RTS and DTR are set high as a hippie on shrooms on port open.
In case of common ESP8266 interfaces, high RTS sends the module to reset state (and holds it there), and high DTR (connected to GPIO0) at reset time sets it to programming mode.
In case of Arduino, DTR pulsed high causes reset (and can be held high afterwards as the reset line is connected via a capacitor). Sometimes RTS is used too.
An unsolvable-in-common-software problem is with the RTS line, which on linux always goes high on open() call. That would need a kernel patch. Some are floating around.
Solution approach
- Try to look around the net for some utility, try socat and others, putz with stty, fail
- Write it in good ol' C
Command
sercat (compiled Apr 20 2021, 01:15:40)
cat for serial ports, with RTS/DTR control, for arduino, ESP modules and microcontrollers
Usage: sercat </dev/ttySomething> [-b speed] [-dtr] [-rts] [...]
-b <baudrate> default 115200, 0=leave as is
-dtr set DTR high (default: low)
-rts set RTS high (default: low, unavoidably pulses high on port open due to linux kernel
-dtrp pulse DTR high on start, for 500 ms
-rtsp pulse RTS high on start, for 500 ms
-pt <n> pulse time in ms (default: 1000)
-raw no filtering of unprintable characters (default: replace with '_')
-hex show unprintables as [hex], replace with '_'
-notty don't set RTS/DTR and baudrate, for timestamping only
-nl <n> exit after n input lines
-ns <n> exit after n seconds (todo)
-sd <n> delay sending stdin for n milliseconds
-sl <n> delay sending stdin for n input lines
-t <n> line timestamp format, 0..7 (4=line number, 2=line time difference, 1=line time)
-q quiet, no state changes
-espboot show ESP bootloader (start at 74880 bps until ~ld line, then switch to -b baudate
-espboott show ESP bootloader, with timestamps if -t is set
Features
stdin
Unline ordinary cat, data can be fed to the port from stdin, whether manually or via a pipe.
Sercat can act as a rudimentary terminal.
stdin delay
Delays the start of feeding of stdin data to the port, by number of seconds or output lines
- -sd <n> - send after delay of n milliseconds
- -sn <n> - send after port sends n lines of text
Shows sent characters as {char} on stderror unless -q.
control lines and baudrate
- -b <n> - set baudrate (default 115200, use 0 for leaving it alone)
- -rts - set RTS to high (default: low)
- -dtr - set DTR to high (default: low)
- -rtsp - on port open, hold RTS to high for the reset interval, then set low (opposite for -rts)
- -dtrp - on port open, hold DTR to high for the reset interval, then set low (opposite for -dtr)
- -pt <n> - set reset interval (pulse time) to n milliseconds
- -notty - no attempt to set speed or lines, no serial IOCTLs at all
timestamping
Prepends line number, line delay, and/or line time to the output
- -ts <n> - takes a number between 0-7, where bit flags enable/disable line numbering:
- 4 - show line number in square brackets
- 2 - show time difference since the beginning of the previous line
- 1 - show time since port opening (or fall of the reset pulse)
- 7 shows all (handy for profiling), 0 shows none
limited runtime
Sometimes the operation needs only couple of input lines, or should finish after preset time.
- -ns <n> - terminate after n seconds (pulse time not included)
- -nl <n> - terminate after n input lines
filtering
Sometimes, especially at speed mismatch (ESP8266 power-on bootloader for example), garbage comes in. That can confuse the terminal.
By default it is filtered, nonprintable characters (anything below 0x20 that's not CR or LF, anything above 0x7F) are replaced.
- -raw - no filtering, data come as-is
- -nohex - replace unprintables with underscore instead of "[XX]" hex code
ESP bootloader
The ESP8266 bootloader is starting at odd baudrate, 74880 bps. This normally shows as garbage at usual speed of 115200.
Switching in runtime is difficult. The bootloader usually ends with "~ld" message, which is detected and taken as the bootloader output end.
- -espboot sets initial baudrate to 74880, then sets to 115200 (or whatever is set by -b) when ~ld string is detected
- -espboott acts as -espoot, but does not suppress timestamps and line numbers for the bootloader section
Examples
Send a command to ESP8266 running Tasmota, on /dev/ttyUSB1 port, run for at most 5 seconds, send the input on 10th line of output, full timestamping,
pulsing RTS
echo fastsensor 3|./sercat /dev/ttyUSB1 -ns 5 -sl 10 -t 7 -rtsp
*** setting DTR to LOW ***
*** setting RTS to HIGH ***
*** device speed is 115200 bps.
*** sleeping for 1000 msec, with RTS=1, DTR=0
*** setting DTR to LOW ***
*** setting RTS to LOW ***
[1][0.018][0.018]r$_l__|__$_|_______$__c|______r_b__b__oo_lnn____#_p__#l`_{lp_n_______l______#_o_|__l____#__on__l__$ ____nn_$ ___nr___o__#_l`__r__o__#_$ __{l_____$l__$__n__
[2][0.266][0.285]00:00:00.014 UFS: FlashFS mounted with 1904 kB free
[3][0.060][0.345]00:00:00.075 CFG: Loaded from File, Count 160
[4][0.005][0.351]00:00:00.080 QPC: Count 1
[5][0.009][0.360]00:00:00.089 Project tasmota Tasmota Version 9.3.1.2(shad)-2_7_4_9(2021-04-17T02:35:34)
[6][0.537][0.897]00:00:00.627 WIF: Connecting to AP1 iotap Channel 6 BSSId XX:XX:XX:XX:XX:XX in mode 11n as tasmota_F2D2A8-4776...
[7][1.755][2.652]00:00:01.754 WIF: Connected
[8][0.251][2.904]00:00:02.006 mDN: Initialized
[9][0.004][2.908]00:00:02.009 HTP: Web server active on tasmota_F2D2A8-4776.local with IP address 10.0.0.223
{f}{a}{s}{t}{s}{e}{n}{s}{o}{r}{ }{3}{\n}
[10][0.038][2.946]00:00:02.048 CMD: fastsensor 3
[11][0.005][2.952]00:00:02.053 RSL: stat/tasmota_F2D2A8/RESULT = {"fastsensor":3}
[12][0.125][3.076]18:54:17.002 iGC: broadcast: IGORCONF:18FE34F2D2A8:0
[13][0.271][3.348]18:54:17.272 RSL: tele/tasmota_F2D2A8/SENSOR = {"Time":"2021-04-18T18:54:17","ANALOG":{"A0":78}}
[14][0.300][3.649]18:54:17.573 RSL: tele/tasmota_F2D2A8/SENSOR = {"Time":"2021-04-18T18:54:17","ANALOG":{"A0":79}}
[15][0.329][3.978]18:54:18.080 RSL: tele/tasmota_F2D2A8/SENSOR = {"Time":"2021-04-18T18:54:18","ANALOG":{"A0":77}}
[16][1.003][4.982]18:54:19.083 mDN: Query done. MQTT services found 0
[17][0.004][4.986]18:54:19.084 MQT: Attempting connection...
Send a command to ESP8266 running Tasmota, on /dev/ttyUSB1 port, run for at most 2 seconds, send the input on 15th line of output, full timestamping,
show timestamped bootloader data and count its lines
echo fastsensor 3|./sercat /dev/ttyUSB1 -ns 2 -sl 15 -t 7 -espboott
*** setting DTR to LOW ***
*** setting RTS to LOW ***
*** device speed is 76800 bps ***
[1][0.014][0.014]
[2][0.001][0.016] ets Jan 8 2013,rst cause:2, boot mode:(3,6)
[3][0.005][0.021]
[4][0.001][0.023]load 0x4010f000, len 3584, room 16
[5][0.008][0.031]tail 0
[6][0.001][0.032]chksum 0xb0
[7][0.002][0.035]csum 0xb0
[8][0.001][0.036]v3969889e
[9][0.001][0.038]~ld
*** bootloader end detected ***
*** device speed is 115200 bps ***
[10][0.220][0.258]
[11][0.007][0.266]00:00:00.009 UFS: FlashFS mounted with 1904 kB free
[12][0.053][0.319]00:00:00.062 CFG: Loaded from File, Count 190
[13][0.005][0.324]00:00:00.067 QPC: Count 1
[14][0.009][0.333]00:00:00.076 Project tasmota Tasmota Version 9.3.1.2(shad)-2_7_4_9(2021-04-17T02:35:34)
{f}{a}{s}{t}{s}{e}{n}{s}{o}{r}{ }{3}{\n}
[15][0.045][0.379]00:00:00.123 CMD: fastsensor 3
[16][0.005][0.385]00:00:00.128 RSL: stat/tasmota_F2D2A8/RESULT = {"fastsensor":3}
[17][0.524][0.909]00:00:00.650 WIF: Connecting to AP1 apiot Channel 6 BSSId XX:XX:XX:XX:XX:XX in mode 11n as tasmota_F2D2A8-4776...
Send a command to ESP8266 running Tasmota, on /dev/ttyUSB1 port, run for at most 2 seconds, send the input on 15th line of output (which doesn't happen), full timestamping, show bootloader
echo fastsensor 3|./sercat /dev/ttyUSB1 -ns 2 -sl 15 -t 7 -espboot
*** setting DTR to LOW ***
*** setting RTS to LOW ***
*** device speed is 76800 bps ***
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v3969889e
~ld
*** bootloader end detected ***
*** device speed is 115200 bps ***
[1][0.221][0.259]
[2][0.008][0.268]00:00:00.009 UFS: FlashFS mounted with 1904 kB free
[3][0.052][0.321]00:00:00.063 CFG: Loaded from File, Count 191
[4][0.006][0.328]00:00:00.068 QPC: Count 1
[5][0.007][0.336]00:00:00.077 Project tasmota Tasmota Version 9.3.1.2(shad)-2_7_4_9(2021-04-17T02:35:34)
[6][0.589][0.925]00:00:00.666 WIF: Connecting to AP1 apiot Channel 6 BSSId XX:XX:XX:XX:XX:XX in mode 11n as tasmota_F2D2A8-4776...
Download
Sources:
Binaries (may not run on earlier or later systems, due to .so dependencies):
TODO
- Ctrl-R, Ctrl-I for manual reset pulses
- Canonical/noncanonical console input modes
- Better error messages
- World peace
- Get laid
- Not necessarily in this order
If you have any comments or questions about the topic, please let me know here: |