There are plenty of terminal programs to access the serial console from minicom or screen to Putty. But Willy Tarreau was not quite happy with those tools, so he decided to write his own: Bootterm.
I was terribly fed up with the current state of serial terminals, which either don’t cope well with errors, or take ages to start, making you lose the first characters, or don’t support non-standard speeds etc. I finally wrote mine to address all that at once, plus support for automatic port detection (the last registered one is the good one by default), waiting for the port to be ready, and also support fixed or timed captures. And a few environment variables make it possible not to type any argument at all yet have the expected behavior. If that’s something of interest to you, you can check it there:
https://github.com/wtarreau/bootterm
It’s still young (no support for automatic speed switching nor macros yet) but pretty usable, and I already switched to it
I happen to have BBC Doctor Who HiFive inventor coding kit connected to my laptop right now, so I gave it a try in Ubuntu 20.04:
1 2 3 4 |
git clone https://github.com/wtarreau/bootterm cd bootterm make sudo make install |
Usually, I check the serial interface by running dmesg, right after connecting the device:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[671497.372868] usb 1-1: new full-speed USB device number 69 using xhci_hcd [671497.547016] usb 1-1: New USB device found, idVendor=1366, idProduct=1061, bcdDevice= 1.00 [671497.547022] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [671497.547026] usb 1-1: Product: HiFive [671497.547029] usb 1-1: Manufacturer: SEGGER [671497.547031] usb 1-1: SerialNumber: 000979421764 [671497.578086] cdc_acm 1-1:1.0: ttyACM0: USB ACM device [671497.587098] cdc_acm 1-1:1.2: ttyACM1: USB ACM device [671497.599064] usb-storage 1-1:1.5: USB Mass Storage device detected [671497.599272] scsi host2: usb-storage 1-1:1.5 [671498.631385] scsi 2:0:0:0: Direct-Access SEGGER MSD Volume 1.00 PQ: 0 ANSI: 4 [671498.631728] sd 2:0:0:0: Attached scsi generic sg2 type 0 [671498.632163] sd 2:0:0:0: [sdc] 21829 512-byte logical blocks: (11.2 MB/10.7 MiB) [671498.633051] sd 2:0:0:0: [sdc] Write Protect is off [671498.633054] sd 2:0:0:0: [sdc] Mode Sense: 0b 00 00 08 |
Bootterm allows you to list all serial devices connected to your host:
1 2 3 4 5 |
bt -l port | age (sec) | device | driver | model ------+------------+------------+------------------+---------------------- 0 | 0 | ttyACM0 | cdc_acm | CDC * 1 | 0 | ttyACM1 | cdc_acm | CDC |
The * in the list means it’s the last connected USB device which in most cases means the serial console you’d want to access. It will be selected by default if you don’t type the device in the command line. That means you don’t need to even check the device use, simply run bt to connect to the board:
1 2 3 4 5 6 7 8 9 |
sudo bt No port specified, using ttyACM1 (last registered). Use -l to list ports. Trying port ttyACM1... Connected to ttyACM1 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help. at_setupCmdADC[151]: argc 2 eFuse Two Point: NOT supported eFuse Vref: Supported Characterized using eFuse Vref at_setupCmdA |
Cool! It just works out of the box! No need to check for device, nor baud rate.
You’ve probably found yourselves wanting to check the output from the bootloader, as soon as you connect the device. If you’re using a USB to TTL debug board that’s fine, but if you’re using one of those boards with built-in serial like the HiFive board I’m using now, this normally involves plugging the board to the USB board, finding out the device name, connect to serial, and then rebooting the board. But with bootterm you can simply use the n parameter which stands for “New”:
1 |
sudo bt -n |
This will wait for a new USB device, and then automatically connect to the serial console. Let’s try it with the HiFive Inventor board.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
0 ports found, waiting for a new one... port | age (sec) | device | driver | model ------+------------+------------+------------------+---------------------- 1 | 0 | ttyACM1 | cdc_acm | CDC Trying port ttyACM1... Connected to ttyACM1 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help. I (14) boot: ESP-IDF v3.3 2nd stage bootloader I (14) boot: compile time 15:55:21 I (14) boot: Enabling RNG early entropy source... D (17) boot: magic e9 D (20) boot: segments 04 D (22) boot: spi_mode 02 D (25) boot: spi_speed 00 D (27) boot: spi_size 02 I (30) boot: SPI Speed : 40MHz I (34) boot: SPI Mode : DIO I (38) boot: SPI Flash Size : 4MB D (42) bootloader_flash: mmu set paddr=00000000 count=1 size=c00 src_addr=8000 src_addr_aligned=0 D (51) boot: mapped partition table 0x8000 at 0x3f408000 D (57) flash_parts: partition table verified, 6 entries I (62) boot: Partition Table: I (66) boot: ## Label Usage Type ST Offset Length D (73) boot: load partition table entry 0x3f408000 D (78) boot: type=1 subtype=1 I (81) boot: 0 phy_init RF data 01 01 0000f000 00001000 D (88) boot: load partition table entry 0x3f408020 D (93) boot: type=1 subtype=0 I (96) boot: 1 otadata OTA data 01 00 00010000 00002000 D (104) boot: load partition table entry 0x3f408040 D (108) boot: type=1 subtype=2 I (112) boot: 2 nvs WiFi data 01 02 00012000 0000e000 D (119) boot: load partition table entry 0x3f408060 D (124) boot: type=40 subtype=0 .... |
This connects automatically to the serial console from the ESP32 module on my board. Pretty neat. But there’s also a serial console for the SiFive Freedom E310 microcontroller which we can access by specifying the device:
1 2 3 4 5 6 7 8 |
sudo bt /dev/ttyACM0 Trying port /dev/ttyACM0... Connected to /dev/ttyACM0 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help. Hardware: HiFive Inventor Board Bootloader Version: 2.40 09/10/2020 12:17:19 Mfg. Test Version: 1.81 09/10/2020 12:17:19 Mfg |
If I press the reset button and the board I can get the boot log from the RISC-V MCU:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Bootloader version: 2.40 09/10/2020 12:17:19 Sleep BK1 0x00000000 BK15 0xbed0bed0 After BK1 0x00000000 BK15 0xbed0bed0 PMU IE 0x0000000b CAUSE 0x00000101 BK1 0x00000000 BK15 0xbed0bed0 Hardware: HiFive Inventor Board Bootloader Version: 2.40 09/10/2020 12:17:19 Mfg. Test Version: 1.81 09/10/2020 12:17:19 Mfg. Location: SX Board Assembly: HFB05 Board Version: 5 Board Revision: A Serial Number: 001331 Date Code (WW/YY): 32/20 WiFi MAC: 24:6F:28:6C:D0:44 BLE MAC: 24:6F:28:6C:D0:46 Board Status: PASS Checksum: 5581 Hardware - Default BLE serial Boot - Tynker VM Version: 1.4 Boot - Default Name: HiFive Boot - Default Passcode: 0x30303030 Boot - Allocated 49168 bytes of memory **** Tynker VM is ready **** |
It’s much easier to use compared to minicom where I’ve had to enter setup mode, type the serial board, select the baud rate and disable hardware flow control before accessing the serial console. Let’s not forget how easy it is to forget the command to exit the program too. But wait… how do we exit bootterm? We are informed about the command each time we start the program:
1 |
Escape character is 'Ctrl-]'. Use escape followed by '?' for help. |
So it’s not too hard to access the help:
1 2 3 4 5 6 7 8 9 10 |
BootTerm supports several single-character commands after the escape character: H h ? display this help Q q . quit P p show port status D d flip DTR pin R r flip RTS pin F f flip both DTR and RTS pins B b send break C c enable / disable capture Enter the escape character again after this menu to use these commands. |
Hopefully, the use of the right-square-bracket ‘]’ will not cause issues with some keyboard layouts. But Willy must have already thought about this potential problem, and provided a method to change the escape character as well…
You can adjust the escape character with bt -exx command with options listed on the table on the right.
The program will use 115,200 bps baud rate by default, but you’ll find an option to change that:
1 |
bt -b 74880 |
Bootterm could also be used as a serial port detector in conjunction with other scripts, as the following command line report the last connected USB device without any extraneous strings:
1 2 |
bt -npq ttyUSB2 |
Bootterm C program is still under development, and Willy plans to implement automatic speed switching and macros. He invites anybody to try it out and report issues on Github.
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
Thank you Jean-Luc!
FWIW I’m now finding it convenient to ignore the ports I don’t use by default, and to wait for any other port to show up. Here’s what I’m setting in my PC’s .profile for this:
I’m now working on adding support for macros. The idea is to allow to define some based on matching rules for the terminal (i.e. enable some for some chips that you know correspond to a specific board). I’d really want to have long “setenv bootargs” and “tftpboot” commands supporting environment variables by just pressing F1 or F2!
I’ve also started to have a look at FreeBSD and with the help from a friend, figured how to auto-detect ports there as well. Not implemented yet 🙂
One thing I thought of that might be neat is integration with micropython. From what I remember you get a standard python looking REPL and then you can use some tools that switch to a special mode to push and pull files. Having to switch back and forth between minicom and the tools was a pain.
In my opinion that would fall into the “file transfer” category. I initially wanted to implement xmodem as it works basically everywhere, and a few extras like injecting Lua code to send or receive files. Micropython very likely works in a similar way, so we should likely plan a generic approach to file transfer and support various methods. Maybe we should think about a simple API to list remote files, receive and send them.
>In my opinion that would fall into the “file transfer” category.
>I initially wanted to implement xmodem as it works basically everywhere
xmodem would be nice. xmodem + some macro magic to tell u-boot to load via xmodem with a higher than normal baud rate doing the switch to/from the higher baud rate automatically would be super handy for boards where ethernet doesn’t work in u-boot but you need to get a kernel into memory to recover it.
>Maybe we should think about a simple API to list remote files,
>receive and send them.
That sounds good.
I just remembered how bad minicoms file selection thing is. I still don’t know how to get it to navigate directories properly.. 😉
Will definitely be trying this out! Have been using screen, but it wasn’t really built for this purpose.
BTW regarding Ctrl-] it should not pose any issue as it’s been successfully used by the venerable telnet for about 40 years now! That’s also why I reused it by default, figuring telnet is rarely used nowadays, and we shouldn’t expect to see it and bt chained too often. Alternately kwboot’s Ctrl-\ looks good as well (and we should even less commonly chain kwboot and bootterm :-))
Nice job Willy.
I’ll try to use it for my review of the RockPiS.
I hope it’ll work on arm64.
It will work, some captures in the readme were taken on an rpi4 filled with USB adapters 🙂
Tried it out, it works nicely. I’m perhaps too used to picocom, though 🙂 It seems like most of the missing functionality can fairly easily be implemented using a short bash snippet or alias, e.g.
to wait for a device to enumerate.
Would definitely want to include exclusion rules for my built-in WWAN (GSM modems), now that I can see how to do that. Perhaps it might be an option to blocklist specific drivers too? e.g. qcserial is unlikely to ever be an external device, so setting an environment variable to ignore those would be handy.
This is written on the paper that lies on my desk 🙂 But that’s a good example indeed! I also want to support matching/excluding descriptions. When they are filled they tend to be more precise than the driver alone.
Finally I just did it, it was trivial. Just export “BT_SCAN_EXCLUDE_DRIVERS=qcserial” and it will do the job.
Nice, thanks! Works perfectly!
For anyone wanting a terminal with a GUI, I would recommend YAT (yet another terminal).
Looklike awesome and litle C code source!
I like to use gtkterm but i want to try the great “Waiting for a new serial port”
I think a terminal emulator you could directly boot into from grub would be interesting and useful for testing, i.e. no OS required
Not that much because it would require an unused machine with a keyboard and screen. For most people using SBCs, it’s easier to find an already running machine and open a window on it than to find a spare set of keyboard+screen+motherboard+bootable device.