UART

From linux-sunxi.org
Jump to navigation Jump to search
A common CP2102 3.3V capable USB UART module

A UART (stands for universal asynchronous receiver-transmitter) or serial console is absolutely essential when doing bootloader or kernel development on any computer. Due to the lack of a standard PC BIOS and the VESA BIOS that goes with it, access to the serial console on ARM devices is even more important than on the PC.

Even if you do not intend to do much U-Boot or kernel work, access to the serial console will be a life-saver when anything goes wrong.

Before you start

Do not connect the RED WIRE unless you want to power the device via UART. Note that the UART power wire probably won't deliver enough power for powering a large SBC. Even a rather small ESP8266 might run out of power with some USB UART dongles.

UART hardware

PC Serial port

Currently, all of the available sunxi hardware requires a 3.3V UART. If you buy a voltage stepper module ("level shifter") you might get away with attaching it to the serial port of your IBM PC (RS232), but this is rather cumbersome. It is much much easier to just buy a 3.3V USB UART module.

UART-USB dongle

Currently, all of the available sunxi hardware requires a 3.3V UART. Popular chips for such modules are the Silicon Labs CP2102 and the Prolific PL2303HX which are both cheap and relatively easy to find. Many cheap chinese dongles come with either of these or a CH340 based design. They all are supported by mainline Linux.

If you don't know what to buy, consider one that explicitly has 3.3V and 5V printed on the board -- it will probably be compatible with both 3.3V TX/RX. Please note that the cheap dongles will probably leak more power to the SBC, which might cause issues if you want to reset or shut down the board properly. If you want to avoid this power leakage, google for (optically) isolated USB-UART designs. If you already have a cheap dongle, you could try adding some resistors or diodes between the dongle and the SBC or try a thin USB extension cable. These might lower the leakage just enough to enable resetting the board.

Exclamation.png Unfortunately, many TTL adapters are very poorly documented. The actual available voltage level (1.8/3.3/5/…V) is either switchable, or a fixed arbitrary value depending on adapter design. Also adapters with the board embedded inside a case tend to have just wires sticking out at one end, with no documentation regarding which wire is which. If in doubt use a multimeter.

Sample measured values (against USB shell when connected to USB only):

  • DX this or this board SJ-039 V1.0 3V3 3.5V, GND 0V, TXD 3.5V, RXD 1.8V, 5V 4.9V. When connected to CB/CT and the board is powered off the RX LED is lit. The power led on the board also lights up slightly.
  • Some PL2303HX 5V TTL USB adapter - board USB-STC-ISP GND 0V, RX 4.6V, TX 4.9V, 5V 5V, 3.3V 3.4V - this won't work - the voltage is too high for cubieboard and would probably damage it. Untested due to lack of 5V uart.

Using an Arduino

If you have an Arduino USB lying around, you can use it as a UART-USB dongle/converter. Arduino USB and his successors (UNO, Duemilanove, Diecimila, NG, Extreme) have a detachable microcontroller and a USB-to-serial converter. You can use them by carefully taking out the microcontroller from its slot and connecting pins as described on Attaching the UART module. Connect Ardunio's RX (pin 0) to the board's RX, TX (pin 1) to TX and GND to GND. Do not connect VCC.

No driver is needed if you are using Linux. For Windows check driver installation instructions on Arduino's website.

Another alternative to disable the Arduino chip is to wire the RESET pin to the GND pin. Some new Arduino chips are soldered on the board, and cannot be removed easily.

USB serial gadget

There is also the option to use the USB serial gadget driver. The driver activates only after the kernel has loaded so it won't be able to display U-Boot messages, but at least it can be used to analyze the kernel logs and for logging in. If you're going to use USBBoot anyway, this might be a viable option.

Using the serial console

Once you hook up your usb module to the host, you should see something like the following appear in your syslog (among other messages):

usb 1-1.3: cp210x converter now attached to ttyUSB0
or
usb 4-1: pl2303 converter now attached to ttyUSB0

You see here to which tty your UART is connected to - and you can now use it through one of the programs listed next.

Troubleshooting / device file permissions

You might get the following error when trying to access the serial port

 $ sudo cu -s 115200 -l /dev/ttyUSB0
 cu: open (/dev/ttyUSB0): Permission denied
 cu: /dev/ttyUSB0: Line in use

The reason why you cannot access the serial port even if you are root, is due to additional kernel-level security restrictions (such as AppArmor or SELinux). For the case of Ubuntu, which has AppArmor, your account needs to be member of the group dialout. To add your account to the dialout group, run the command

 $ sudo usermod --append --groups dialout myusername

Then, log out and log in again.

Consider some other solutions listed here.

You could also try this, but it only works until reboot / device is disconnected:

sudo chmod 666 /dev/ttyUSB0


Software

Linux / OSX

'If you are using OSX, you should replace /dev/ttyUSB0 with /dev/tty.PL2303-00001014'

cu

cu is an utitlity that comes with popular system distributions like Fedora, Debian, Ubuntu, NetBSD, etc. It can be used to talk to a device connected to a serial port. On Linux with the serial cable as the only USB serial port

 stty -F /dev/ttyUSB0 -crtscts  # turn off hardware flow control - the cable has no wires for that
 cu -s 115200 -l /dev/ttyUSB0

screen

screen /dev/ttyUSB0 115200

Be sure to set the baudrate to the maximum of 115200, otherwise your console might not function reliably.

To exit screen is tricky: Ctrl + 'a' followed by '\' - Exit screen and terminate all programs.

gtkterm

With gtkterm, a serial terminal tool with minimum graphic interface:

gtkterm -p /dev/ttyUSB0 -s 115200

tinyserial

On Archlinux, the command com from tinyserial package can be used:

com /dev/ttyUSB0 115200

Windows

On Windows you can use software like TeraTerm or Putty or similar which can connect over serial line.

Attaching the UART

With a UART connector available

If you are using a development board, or a device like the Mele A1000, you should have a nice connector available for attaching your UART module to. If you are extremely lucky, the pin functions will even be printed on your board. Many will not be so lucky, especially with tablets. How to deal with those tougher cases is described below.


Exclamation-red.png Do not connect the VCC or 3.3V/5V pin, as that will damage your device!
Some modules have color-coded leads, in that case the red wire should correspond to VCC.

Your USB UART module should have 3 pins:
RX goes to TX
TX goes to RX
GND goes to GND on both

If you have wired things up correctly, (read serial console) and boot your device you should see boot messages flying by. If this does not work, try swapping RX/TX around.

If it's not clear which pins are which on your target, use a multimeter to determine GND and VCC. You can do this by measuring the voltage difference between, for instance, shielding of a USB connector and the UART pins, on a running device.

Without a UART connector

Finding the UART pins on a device not meant for development might get quite tricky. It involves disassembling your device with great care, some basic (logical) troubleshooting, some soldering, and then some creativity to be able to export your serial connection to the outside world.

Exclamation.png You will be seriously voiding your warranty here. The likelihood of being left with a damaged device is very high. You might even totally destroy your device. So you need to be extremely careful.

Like with everything on this wiki, you yourself are responsible for the actions you take. If you do damage or destroy your device, it's your own fault.

If you do NOT want to risk damaging or destroying your device, then this howto is not for you. If you are not comfortable with disassembling your device, soldering wires to it, or are lacking some of the necessary equipment, get someone else to do it for you, or don't do it at all.

Necessary tools and skills

You need some very basic electronics equipment. A multimeter, your usual collection of banana plug cables, probes and hirschmann clamps, a fine soldering iron (temperature controlled preferred), good solder and flux.

You will also need some jumper wires, which are easily scrounged off of an old PC case. Preferably black, green and white, in a triple housing.

Disassembling the device

Disassembling your device is outside of the scope of this document. By using google, you might be able to find someone who has already taken your device apart, and see the process documented on some android forum. Failing that, there are tons of tablet disassembly guides on the likes of youtube. But do use a plastic tool instead of a screwdriver for prying your device open.

You probably need to be able to access the backside of the motherboard as well, so make sure that the board is free. Do not cut any wires, you will need your device to work, even when all of it has been laid bare.

Inspect the mainboard

Often times, you can get lucky, and the UART can be spotted easily. The Hyundai A7HD is a great example of that as it has a full serial port on big pre-tinned pads available. In case of the Hyundai A7, due to the limited number of testpads, and the way they were grouped, it was also clear which were the UART pins.

When you are not so lucky, you get presented with a motherboard with a big load of test-pads. This leaves you no option but to systematically try each one of them.

Regardless of whether the connections are easy to find or not, you still pretty much need to run through the procedure as listed below.

Attaching the UART module

Boot your device, and get the original OS running.

Attach your UART module to your host PC and run your console program on it.

Connect GND of the UART module to a convenient ground location on your board, and attach a probe to RX of the UART module.

If you now touch the probe to ground, you should see some broken characters appear on your console program. If not, check whether GND is wired up correctly, or swap RX/TX around on the module side.

Make some noise

Normally, your device will only sporadically send data out the serial bus, so the chances of seeing any text scroll past on the console, is pretty low.

A small tool called serial_noise is available, and it is statically compiled and verified to run on many android systems (source code is available here). Download it to your device, and run it.

When serial_noise has successfully started, and has found serial consoles in /dev/, it says:

Flooding serial consoles with text...

It will then be sending the /dev/ device names out to all the detected serial consoles on the system.

Find TX

You can now go and carefully touch the testpads with your probe, for a few seconds each until you see a device name scroll past. From time to time, verify that your setup is still working by sending some garbage to your hosts console program by touching ground with your probe.

Find RX

If or when you have found TX, you should find RX nearby.

Attach a second probe to the TX pin of the UART module.

With the other probe on the TX pad on the device still, you can now go and probe for the RX pad.

The easiest way to verify this is to touch a pad with the probe, and then typing things into the console program on your host computer. If you see your characters echoed back, then you have successfully located the RX pad.

Cable routing

Before you solder on the jumper wires, figure out how to get your serial connection available to the outside world.

With space at a premium in any mobile device, it is not easy to find a good solution here. The punishment for bad routing is quite severe. Your device might not close anymore, and there might be pressure on your devices LCD, leading to uneven backlighting and colours. So do take care at this stage.

A good example of bad routing and the damage that it causes can be seen on the Hyundai A7HD page.

Make a point of clearly marking which wire is GND by using a brown or black wire for it. If you use jumper wires from an old PC case, try use a triple connector to make life easier in future.

Great for development, but not very socially acceptable.

Soldering the jumper wires

The usual recommendations for small electronics soldering apply.

Reassemble your device

And if all goes well, you should now have a tablet with something strange hanging out. You should be able to attach your UART module to it directly, fire up your console program and immediately get a console.

Now you can do low level development on your tablet, even when on the move. Just don't bring it up in a conversation with normal people if you still want them to respect you afterwards.

No UART to be found

There is a (slight) possibility that the UART simply is not enabled in script.bin. In that case, first finish off the Retrieving Device information howto from the New Device howto, so that you make sure that all the necessary data from the android installation has been retrieved. Then, still following the New Device Howto, try to set up a linux on an SD card and boot from that. You can then try editing script.bin, to enable the UART, and you can then try to locate the UART on the board again.

When all else fails

In this case, you usually can still use the SD/micro-SD connector with a MicroSD Breakout Adapter. Do note that this requires an altered U-Boot target and an altered script.bin.

You lose the functionality of the SD-Card, but you can do U-Boot or Kernel development over USBBoot instead.

Common Pitfalls

Serial output stops when kernel uart driver is loaded

If you have working serial output with U-Boot, but the output stops just after loading the kernel uart driver, like so:

<6>Serial: 8250/16550 driver, 8 ports, IRQ sharing disabled
<6>[uart]: used uart info.: 0x01
<6>[uart]: serial probe 0 irq 33 mapbase 0x01c28000
<6>sunxi-uart.0: ttyS0 at MMIO 0x1c28000 (irq = 33) is a U6_16550A

Then there might be something wrong with your kernel commandline.

Please verify that you have "console=ttyS0,115200" in your commandline, for instance in your U-Boot boot.cmd:

setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait panic=10 ${extra}

Make sure that the baudrate is provided as well.

U-Boot stops after initial load

If U-Boot behaves erratically, and stops after initial load, with the last line printed of the boot log repeating the first lines, there might be something wrong with your UART pads, or the cabling to it.

Here is an example of the boot log, note the repetition of the first line:

    U-Boot SPL 2014.04-10710-g509d96d (Sep 05 2014 - 18:47:53)
    Board: Iteaduino_Plus_A20
    DRAM: 1024 MiB
    Failed to set core voltage! Can't set CPU frequency
    spl: not an uImage at 1600
     
     
    U-Boot 2014.04-10710-g509d96d (Sep 05 2014 - 18:47:53) Allwinner Technology
     
    CPU:   Allwinner A20 (SUN7I)
    Board: Iteaduino_Plus_A20
    I2C:   ready
    DRAM:  1 GiB
    MMC:   SUNXI SD/MMC: 0
    *** Warning - bad CRC, using default environment
     
    In:    serial
    Out:   serial
    Err:   serial
    Net:   emac
    Hit any key to stop autoboot:  0
    sun7i#
    sun7i#
    sun7i#
    sun7i#
    sun7i#
    sun7i# U-Boot 2014.04-10710-g509d96d (Sep 05 2014 - 18:47:53) All2###### U-Boot 2014.04-10710-g509d96d (Sep 05 2014 - 18:47:53l

When you probe the RX and TX lines with an oscilloscope you will see an erratic serial signal.

The issue above was a short between RX and TX. Please verify that this is not the case if you have some of the above symptoms.

UART transmits intermittent garbage when clocked with PLL_PERIPH0(1X)

Problem was observed on an H5 (NanoPi Neo 2 2017).

Switch UART clock source (APB2) to use PLL_PERIPH0(1X) running at nominal 600MHz. Confirmed baud rates were as expected.

UART works but transmits intermittent garbage characters. Oscilloscope confirms that the wrong character is being transmitted and that it's not being mis-received. Observed on a 115000 baud link.

Solution is to reduce the clock rate to the UART by setting a divide ratio in APB2_CFG_REG. I could achieve my baud rates by setting CLK_RAT_M=12 (divide by 13).

Note the RM has the following to say when switching clock rates: "Make sure that the clock source output is valid before the clock source switch, and then set a proper divide ratio; after the division factor becomes valid, switch the clock source."

I used writel(CLK_24M | NEW_DIV_RATIO,APB2_CFG_REG);writel(CLK_PERIPH0(1X) | NEW_DIV_RATIO,APB2_CFG_REG); and it worked fine.

Board won't shut down completely

The UART link may often leak some current, which prevents the board from completely shutting down. As a result, the board might not switch to FEL boot mode. Disconnecting and reattaching the UART cable should solve this issue. If one needs to constantly reboot, this can become an issue. There are (optically) isolated UART modules that don't leak power, but one could also experiment with a resistor in the host TX pin or using USB UART dongles with a long extension cable (will weaken the current just enough to prevent the board from staying on).

See Also