I recently salvaged some LCD screens from a couple scrapped video greeting cards; and while researching the connector type for those screens (40-pin direct RGB), I ended up stumbling upon a compatible cute mini dev-board called Lichee Pi Nano. It is powered by an Allwinner F1C100S processor and is about 25mm x 30mm – barely big enough to fit the LCD connector!
It can run Linux, but only a very pared-down build; also, with smaller manufacturers like this the documentation can be spotty, and generally getting anything to actually run can be a crapshoot. This seemed like a good practice run for building an embedded Linux distro, so I decided to try it for myself as a challenge.
First, I needed to solder connections for power and onboard UART to be able to see the boot log. I also attached a wire for the SPI Flash CS pin to be able to trigger FEL mode.
The board was connected to my computer via a standard FTDI 3.3v cable.
To build the boot SD card image I ended up using a tool called Buildroot: a one-stop-shop for downloading and compiling everything required for a custom bootable Linux distribution:
- SPL and bootloader (U-Boot)
- Linux zImage + device tree
- userland filesystem (rootfs)
- overall combined disk image for initial flashing
The Lichee Pi Nano actually comes with a manufacturer-supplied Linux build preloaded to the onboard SPI Flash. Official instructions have a pretty thorough walkthrough on how to build one’s own image, too, but it felt a bit “hairy” because it relies on hand-tuned Bash scripts for overall orchestration. They do use Buildroot, but in a very limited fashion, whereas I wanted to use as much of the stock automation capabilities as possible.
I started with a fresh Buildroot checkout with a blank config, and then started combing for useful bits in any existing configuration files and splicing them together. I also integrated the image build script from the Funkey Lichee Pi Zero repo above, and hooked up manufacturer-provided U-Boot and Linux forks to work as part of standard Buildroot pipeline. All in all, an exercise in tracking down and cross-referencing various docs, files and scripts – a taste of how real engineering works, no doubt.
Luckily, there was very little trouble with the build itself. At first, I had issues compiling the
gcc toolchain and tried temporarily using the external binaries compiled by Linaro GCC. That actually produced a bootable kernel, but userland code did not work – kernel panic on
/sbin/init (I suspect issues with
glibc). Then, when I switched back to using a home-built toolchain, it worked fine and booted!
Finally, I had to tweak the DTS file to make device tree match the LCD resolution settings. This is the end result: it boots to UART shell in 3-4 seconds only!
It made sense to open-source the resulting automation setup, of course.
I organized my Buildroot customizations as an external config extension rather than a fork of the mainline repo. The mainline Buildroot version is used, but Linux and U-Boot source repos are custom forks: I still had to rely on branches maintained by Lichee Pi Nano maintainers because some of the hardware support is not merged into upstream (and might never be?). Luckily, Buildroot has very good support for custom source forks and branches in its build orchestration; even custom DTS files are supported.
This is the resulting repo with Lichee Pi Nano configuration for Buildroot. It implements a “single-click” build for the entire OS image, based on latest vanilla Buildroot version. For now, only the SD card boot image is supported (no on-board SPI Flash build). However, I have tested booting from on-board Flash and it does work in principle, just needs better cleanup. Booting without SD card does seem quite slow, though.
Building a custom embedded distro for Lichee Pi Nano was a great exercise in low-level Linux “sysadmin” and hardware hacking; I learned a lot about Buildroot, device trees and kernel configuration tweaks. Plus, assembling and tidying up various shell scripts and config files was oddly satisfying; compiling the entire OS image via a single
make command is a nice automation win. It’s funny, the board fits in the palm of my hand and I have spent so long curating its contents: it feels almost like a pet by now?