Tag: OpenWRT

Serial UART console

Most simple and common way to connect almost any embedded device is serial UART port. You can find one inside any Smart TV or Media Center, WiFi Router and almost any kind of complex electronic device provides this port. The reason to expose this port may be different, but usually is used for maintenance, debug and diagnostics. Be careful with [un] authorized accesses to any device: please check device documentation and contact support first.

For everything you would like to know about serial communication please refer to this article: https://www.freebsd.org/doc/en_US.ISO8859-1/articles/serial-uart/index.html

Original specification for DB9 and DB25 connectors defines a lot of control and synchronization signals like DTR – “Data Terminal Ready”, DSR – “Data Set Ready” or RI – “Ring Indicator”. Signals used especially for synchronization with ancient and slow terminals with small buffers. Currently many devices successfully use only TX and RX pins for serial communication and all other pins are simply useless.

Actually there are many ways to connect to the serial port, for example you can use “USB to Serial” converter or “Serial Bluetooth” module; almost any embedded development kit should support UART / USART connection. Before selecting your converter, check signal levels, is common to find 5v and 3.3v devices. Do not mix unless your 3.3Volt device is specifically tolerant to 5volt signals, otherwise signal level converter is required. Some old devices or also special purpose serial devices may use +/-12 volt signal.

This kind of serial connection is not intended for high bandwidth or long range communications. Rather that it’s simple and robust enough to fulfill most of the basic but essential communication tasks.

Common baud-rates and maximum theoretical data throughput:

7bit data
No parity
8bit data
No parity
8bit data
1bit parity

Although simple serial console I/O is powerful enough for many tasks where the error is negligible, big data transfer requires error handling and synchronization, like XON / XOFF or parity bit. Is also a good practice to add CRC to the transmitted data block, over then simple parity check. Because this type of communication may suffer of erasures and multi bit errors.

A lot of software and protocols was developed to support serial communication remote console and file transfer, like “[X|Y|Z]MODEM” or “Kermit”, “minicom” and “Putty” and many others more or less famous.

A simple and elegant way to connect router’s serial console is through HC-06 Slave bluetooth module.
This module exposes the SPP (Serial Port Profile) protocol for remote devices. Then, any Bluetooth Master near the router can connect it, obviously knowing the correct pin.

TL-MR3220 serial port connected to bluetooth HC-06 module. Supply of 3.3v is provided by router board red wire. Black is ground, TX and RX (Green and White) for serial I/O.

Router board console via bluetooth with Putty.

First, configure HC-06 module for 115200 bps 8 bit data, no parity bit and one stop bit, then connect it to the router. If provided power supply is sufficient to power-up bluetooth module, we will see blinking red led. Module consumption under 3.3v is around 4mA – 8mA for idle state and 20mA – 40mA for normal operation.

Python setup script for HC-06 serial bluetooth module: https://github.com/netquote/hc_utils

Bluetooth module connection with level shifter (5v to 3.3v) and FTDI Serial to USB converter
$ python3 hc_setup.py /dev/ttyUSB0 -p N --set-pin 1234 --set-name BTS00 --set-rate 115200 --set-parity N

 Guessing bit-rate and parity on /dev/ttyUSB0 …
   Rate: 1200, parity: N 
   Rate: 2400, parity: N 
   Rate: 4800, parity: N 
   Rate: 9600, parity: N 
   Rate: 19200, parity: N 
   Rate: 38400, parity: N 
   Rate: 57600, parity: N 
   Rate: 115200, parity: N 
 AT device detected.
 Open serial port: /dev/ttyUSB0, bit-rate: 115200, parity: N 
 Device version: linvorV1.8 
 Set name OK
 Set pin OK
 Set baud 115200 
 Set parity  None

Deal with serial ports from source code is pretty straightforward, like write and read any simple file except seek function which is not applicable. Other things, like serial port name and configuration procedures are OS and language specific.

Example Python script for basic serial I/O:

#!/usr/bin/env python

# Import pySerial library
from serial import *

# Open serial port at "115200,8,N,1", timeout 3s 
ser = Serial(port='/dev/ttyUSB0',

# Write a string

# Read 30 bytes

# Close port

This Python demo script should work on both, Linux and Windows platforms, just change device name to “COM1” on Windows.

Another way to deal with serial communication is “kermit” from: http://www.kermitproject.org
Old-school scriptable tool for almost any modem communication related tasks.

; Kermit script for router firmware update via serial line
; Router: TL-MR3220 v1.2 (original bootloader)
; File: "wrt_ser_upload.ksc"

set line /dev/rfcomm3
set speed 115200
set carrier-watch off
set flow-control none
set handshake none
set prefixing all

; Echo serial line to console

; Clear console input buffer
; Wait for console prompt
INPUT 3 :/#
; System reboot request 
LINEOUT reboot

; Wait for U-Boot prompt 
INPUT 180 Autobooting in 1 seconds
; Login into u-boot console

; Wait for u-boot prompt
INPUT 3 ar7240>
; Prepare U-Boot for incomming file
LINEOUT loadb 0x81000000

; Wait for u-boot ACK
INPUT 3 Ready for binary (kermit) download
; Send new firmware file
SEND ~/openwrt-18.06/bin/targets/ar71xx/tiny/openwrt-ar71xx-tiny-tl-mr3220-v1-squashfs-factory.bin

; Wait for u-boot prompt
INPUT 3 ar7240>
; Erase target flash memory 
LINEOUT erase 0x9f020000 +0x3c0000
; Erase completed  
INPUT 60 Erased 60 sectors

; Wait for u-boot prompt
INPUT 3 ar7240>
; Write new firmware to flash
LINEOUT cp.b 0x81000000 0x9f020000 0x3c0000
; Wait for done
INPUT 60 done

; Wait for u-boot prompt
INPUT 3 ar7240>
; Boot into new system 
LINEOUT bootm 0x9f020000

; Quit

This Kermit script updates OpenWRT firmware for TL-MR3220 router v1.2

Kermit file transfer

Router documentation:
Kermit documentation:
HC-06 bluetooth module documentation:
HC-06 Firmware reference:

TP-Link MR3420 setup OpenWRT v18.06

OpenWrt is a powerful Linux distribution for embedded devices. Especially for routers with reduced memory and performance. This objective has contributed to an extreme level of optimization of this distribution, allowing also a high margin of flexibility and really easy setup.
This distribution usually fits on many embedded devices, the complete list can be found at this link: http://wiki.openwrt.org/toh/start

Don’t expect magics from this configuration, you can’t install all the available software, simply because we don’t have enough RAM / ROM memory. Sometimes it is possible to overcome some limitations, for example extending the RAM memory with the ZRAM or SWAP file, extending the root filesystem with a USB flash memory device. However, a stable and robust configuration requires a careful evaluation of the installed services and their impact on system resources. Software as imagemagick or ffmpeg, which tries to allocate a large amount of memory, will likely fail with the segmentation error.
However, everything comes from source and everything is customizable. You can even avoid to install web interface and configure everything by ssh console and UCI command line tool, or build your own web GUI or Service supported by a solid and flexible cross-build system.
Thanks to the excellent work of all OpenWrt team, time to time, we have a new and fresh release to build.
Check your system requirements first: http://wiki.openwrt.org/doc/howto/buildroot.exigence
This new release includes linux kernel updates, different security and bug fixes.

Clone v18.06 branche:

git clone -b openwrt-18.06 git://git.openwrt.org/openwrt/openwrt.git openwrt-18.06

Or master branche:

git clone git://git.openwrt.org/openwrt/openwrt.git openwrt

Next, update feeds:

cd openwrt-18.06/
./scripts/feeds update -a

Configure build system:

make menuconfig

Select router options:
Install LUCI web interface:

./scripts/feeds install luci

Select Luci web interface from menuconfig:

LuCI --->  1. Collections --->  <*> luci

Choose packages carefully, because we have only 4mb of storage. This amount of memory is enough for many specialized device with a limited set of features like a router or AP. In order to take advantage of many of the packages provided by OpenWrt, it is essential to extend the memory with external USB storage. Blockmount package and root overlay filesystem can do this trick: https://openwrt.org/docs/techref/block_mount

Select block-mount:

Base system --->  <*> block-mount
Kernel modules --->  USB Support --->  <*> kmod-usb-storage
Kernel modules --->  Filesystems --->  <*> kmod-fs-ext4

Another solution is to remove all ip-v6 support. Is configured by default and also supported from kernel side. Hacking on Kernel configuration is especially useful when support for specific hardware is required or simply to enable debugging features or disable something to save space. 

Linux kernel configuration:

make kernel_menuconfig

Careful with kernel settings, most of them are unsafe. Don’t touch things, if you are not aware about what are they really doing. At best, you’ll get a slow kernel with a lot of useless code.

Build firmware:

make -j8

Finally, we can find all binary files in “bin/targets/ar71xx/tiny/”

1,2K giu 13 12:04 config.seed
2,8K giu 13 12:07 openwrt-ar71xx-tiny-device-tl-mr3420-v1.manifest
2,7M giu 13 12:07 openwrt-ar71xx-tiny-root.squashfs
3,8M giu 13 12:07 openwrt-ar71xx-tiny-tl-mr3420-v1-squashfs-factory.bin
3,6M giu 13 12:07 openwrt-ar71xx-tiny-tl-mr3420-v1-squashfs-sysupgrade.bin
1,2M giu 13 12:07 openwrt-ar71xx-tiny-uImage-lzma.bin
3,5M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.bin
3,5M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.elf
1,2M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.lzma
1,2M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux-lzma.elf
4,0K giu 13 12:07 packages
1,1K giu 13 12:07 sha256sums

To program the device for the first time is sufficient to upload “factory.bin” to the router, from it’s own classic web interface as usual. For subsequent upgrades from LUCI web interface use “sysupgrade.bin”.

Wait for the router to reboot, connect to “” with any browser or ssh, then you will be able to set up root password. First Login: http://wiki.openwrt.org/doc/howto/firstlogin

Next topics:
1) Serial debug console
2) Customize your build
3) Remote development

All documentation and howto: http://wiki.openwrt.org/doc/start
Multiple builds in one single checkout: http://wiki.openwrt.org/doc/devel/env
Detailed build instructions: http://wiki.openwrt.org/doc/howto/build
Easy patch management: http://wiki.openwrt.org/doc/devel/patches
Creating packages: http://wiki.openwrt.org/doc/devel/packages