Warming up for some Pine fun
I recently got my hands on a PinePhone along with a Pine64 board and have the aspiration to bring Sculpt OS to this platform. This is a very welcome opportunity to document the process of such a porting effort.
In a previous article, I wrote about the principle steps needed to bring Genode - and Sculpt OS in particular - to a new ARM SoC. Such an undertaking comes with a great deal of uncertainties, namely the inner functioning of overly complex hardware, picking appropriate tools and methodologies, taking informed decisions about porting versus developing drivers, and relating all this to Genode.
Combined, these uncertainties pose a huge barrier. At Genode Labs, we have conquered this barrier a few times in the past, like recently for supporting the NXP i.MX8 SoC. However, the porting of Genode to new hardware should not be left as an activity exclusive to Genode Labs. In order to assist developers outside of Genode's inner circle with joining the fun, we'd like to share what we know. This sharing should have the form of profound documentation that serves as a guide and removes points of friction as much as possible.
To deliver substance, I figured that I should not merely talk the talk by speaking from past experience, but also walk the walk again while writing down my practical steps as I go. So I went forward looking around for tasty hardware, when Pine64 caught my eyes.
I got excited about Pine64 for several reasons.
First, devices in the form factors of the PinePhone and the A64 development boards are readily available at affordable prices. The Pine64 website carries a very positive message, highlighting community, openness, sustainability, transparency, no marketing nonsense.
Second, the products are designed for hackability. This is evidenced by the vibrant developer community, mainline Linux kernel support, and the availability of literally more than a dozen Linux distributions. One can boot the PinePhone directly from SD-card. How cool is that!
Third, the used Allwinner SoC - introduced as early as 2015 - is rather aged. In contrast to bleeding-edge hardware, I would not need to explore unconquered territory. Others have hopefully discovered most pitfalls before me. The SoC seems to strike a nice balance of modern features (64 bit, multi core, virtualization) with modest complexity. The performance of the SoC is notably at the lower end of the smartphone product category. From the perspective of an operating-systems developer, I don't see this as a con but more as a welcome challenge. Will Genode be able to shine on such a constrained device? Let's find out!
The only downside of the SoC worth mentioning is the lack of an IO-MMU as protection mechanism against rampant I/O devices or drivers. So the sandboxing of device drivers can never be water-tight.
We ordered a Pine64-LTS board, a PinePhone, and a serial cable for the PinePhone directly from the online store. For some kind of safety reason, the phone had to be ordered separately. In hindsight, we better had ordered a power supply for the Pine64-LTS board as well. We skipped it as we already have kilograms of AC power supplies of other boards at hand. However, it turned out that kilograms of power supplies with 5mm connectors are of little use when the board features a less mainstream 3.5mm connector. Such details matter sometimes.
Dabbling with the PinePhone was pure joy. I particular loved exploring the work of Ondrej Jirman such as his p-boot boot loader and his ready-to-use multi-distro image that features no less than a dozen Linux distributions on a single SD card! That's just perfect for getting an impression on the variety of mobile-geared GNU/Linux developments. Personally, I found Lune OS (a descendant of Palm WebOS), Sailfish OS, and Ubuntu touch particularly interesting to explore.
For getting my hands dirty with technical work, I'll have to leave the PinePhone alone for a while and turn my attention to the Pine-A64-LTS board. The Pine64 wiki provides the perfect staring point.
The wiki lists numerous ready-to-use Linux distributions. I went for Armbian. Just a few minutes later, after downloading the disk image from https://dl.armbian.com/pine64so/Buster_current, writing the image to an SD card, connecting an HDMI display and a USB keyboard, and booting the board with the SD card inserted, I was greeted with Armbian login, allowing me to login as root user.
At this point, I'm most interested in getting a first overview of the hardware. The following information are insightful:
root@pine64so:/# cat /proc/cpuinfo ... root@pine64so:/# cat /proc/meminfo
Well, that is not too surprising. It's more like a ritual.
root@pine64so:/# dmesg | less
The kernel boot log is quite chatty. The following lines caught my eyes.
[ 2.228675] sun4i-drm display-engine: bound 1100000.mixer (ops 0xffff800010da9a30) [ 2.230477] sun4i-drm display-engine: bound 1200000.mixer (ops 0xffff800010da9a30) [ 2.231001] sun4i-drm display-engine: No panel or bridge found... RGB output disabled [ 2.231018] sun4i-drm display-engine: bound 1c0c000.lcd-controller (ops 0xffff800010da5360) [ 2.231227] sun4i-drm display-engine: bound 1c0d000.lcd-controller (ops 0xffff800010da5360) [ 2.231293] sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get regulator [ 2.231734] sun4i-drm display-engine: Couldn't bind all pipelines components
...once we get to graphics, we have to grep the Linux kernel for "sun4i-drm" and "sun8i-dw-hdmi". Whatever sun4i and sun8i means. Does "dw" stands for Designware? I shudder for a moment...
[ 2.250163] 1c28000.serial: ttyS0 at MMIO 0x1c28000 (irq = 31, base_baud = 1500000) is a 16550A [ 2.250239] printk: console [ttyS0] enabled [ 2.250893] sun50i-a64-pinctrl 1c20800.pinctrl: supply vcc-pg not found, using dummy regulator [ 2.251327] 1c28400.serial: ttyS1 at MMIO 0x1c28400 (irq = 32, base_baud = 1500000) is a 16550A [ 2.251471] serial serial0: tty port ttyS1 registered
...the Linux kernel uses the serial controller at 0x1c28000 by default. That will be the first device we need a driver for. Never heard of a "16550A" device though...
[ 2.277178] ehci-platform 1c1b000.usb: EHCI Host Controller [ 2.277210] ehci-platform 1c1b000.usb: new USB bus registered, assigned bus number 3 [ 2.277359] ehci-platform 1c1b000.usb: irq 22, io mem 0x01c1b000 [ 2.289613] ehci-platform 1c1b000.usb: USB 2.0 started, EHCI 1.00 ... [ 2.291208] ohci-platform 1c1b400.usb: Generic Platform OHCI controller [ 2.291228] ohci-platform 1c1b400.usb: new USB bus registered, assigned bus number 4 [ 2.291342] ohci-platform 1c1b400.usb: irq 23, io mem 0x01c1b400
...an OHCI USB controller, I get a little blast from the past...
[ 2.384988] sunxi-mmc 1c0f000.mmc: initialized, max. request size: 16384 KB, uses new timings mode [ 2.410167] sunxi-mmc 1c10000.mmc: initialized, max. request size: 16384 KB, uses new timings mode [ 2.422925] mmc0: Problem switching card into high-speed mode! [ 2.423025] mmc0: new SDHC card at address 0001
...two multi-media card (MMC) devices, apparently driven by an Allwinner-specific controller. "Problem switching card into high-speed mode!". MMC and problem are almost synonymous. Allwinner will not positively surprise us...
[ 3.412571] dwmac-sun8i 1c30000.ethernet: IRQ eth_wake_irq not found
...the good news is that there is a dedicated Ethernet controller, not merely a USB-network device. The bad news is that the controller is an IP core purchased from Designware. After the deep scars I got from USB on the Raspberry Pi, I was hoping not to touch anything with "dw" in its name again...
[ 9.189128] Call trace: [ 9.191219] ktime_get_update_offsets_now+0x5c/0x100 [ 9.193340] hrtimer_interrupt+0xa0/0x2f0 [ 9.195466] sun50i_a64_read_cntpct_el0+0x30/0x38 [ 9.197542] arch_counter_read+0x18/0x28 [ 9.199712] arch_timer_handler_phys+0x34/0x48 [ 9.201813] handle_percpu_devid_irq+0x84/0x148 [ 9.203971] ktime_get_update_offsets_now+0x5c/0x100 [ 9.206022] hrtimer_interrupt+0xa0/0x2f0 [ 9.208071] generic_handle_irq+0x30/0x48 [ 9.210150] __handle_domain_irq+0x64/0xc0 ... many more lines ...
...a Linux kernel thread died during boot. The "sun50i" symbol hints at an Allwinner-related driver issue. The kernel marches on nevertheless...
[ 9.703995] lima 1c40000.gpu: gp - mali400 version major 1 minor 1 ...
...it's really nice to have a GPU without the need for any proprietary blobs, thanks to the reverse-engineering efforts by the Lima project.
The kernel log is not the only place revealing information about the hardware.
root@pine64so:/# cat /proc/iomem 01000000-0100ffff : 1000000.clock clock@0 01100000-011fffff : 1100000.mixer mixer@100000 01200000-012fffff : 1200000.mixer mixer@200000 ... ... 40000000-bdffffff : System RAM
Here, we get a complete view of the physical-memory layout, including the locations of all memory-mapped devices as well as the actual RAM. The (almost) 2 GiB of physical memory does not start at 0 but rather at 0x40000000.
root@pine64so:/# cat /proc/interrupts
Here, we see how the relationship between devices, interrupt numbers, and CPUs (interrupt routing) as configured by the Linux kernel.
Another point of interest is the device tree that can be found at /proc/device-tree, which is actually a symbolic link to /sys/firmware/devicetree/base.
At this point, it is too early to digest all this information. Let's save it for later. The easiest way is storing data on a USB stick.
When plugging in a USB stick to the second USB port, the kernel's dmesg output tells us that it is detected as /dev/sdb as well as the partitions, e.g., /dev/sdb1 for the first partition.
Knowing the device name of the partition, we can mount its file system at /mnt via mount /dev/sdb1 /mnt.
Now we can copy any files interest to /mnt/.
As an additional function test, one can quickly give the network interface a try. Once when plugging in a network cable to our local network, the LED on the network PHY starts blinking happily, and ifconfig reveals that the board got an IP address from our local DHCP server. A quick wget https://genode.org works just as expected.
Knowing that the board is fully functional when running a Linux-based OS, we have to work towards using the board as an embedded development target. Textual output over serial is the most important prerequisite for that. The times when development boards featured 9-pin D-SUB connectors is long past. Nowadays, we need to look out for the right pins on one of the board's expansion sockets. The board has several of them. So now is a good time to get acquainted with the board's schematics.
The schematics hint at several serial devices (UART). E.g., UART1 at the SDIO WIFI + BT pin header. The go-to solution is not obvious