User Tools

Site Tools


uconsole

uConsole

This page is a work in progress Also note that this is a still in-progress project and the instructions below could be inaccurate.

Introduction

The uConsole by ClockworkPi is a handheld device based on the Raspberry Pi 4 Compute Module, featuring a built-in display, keyboard, and trackball to control the mouse. It looks like this:

Custom Kernel

The uConsole includes a pre-flashed SD card including a non-standard Linux Kernel. The standard instructions for installing the OS simply tell you to download their pre-generated image and flash your SD card with it: this also gives you the custom kernel.

This is fine for a lot of users, but raises some questions regarding how that kernel is made and what is different about it. Personally I don't want to use a kernel which a small company has made for me, especially if there is no transparency into the build process which is the situation here.

Worse still, the kernel version I was given on the SD card was outdated and I heard from others that updating the kernel prevented the built-in screen from working. I decided to spend some time researching their kernel modifications so that I could compile my own updated version.

Building your own

First lets start by following the official instructions, which, for the Pi4 version, are:

git clone https://github.com/raspberrypi/linux.git

cd linux

wget https://raw.githubusercontent.com/clockworkpi/uConsole/master/Code/patch/cm4/20230630/0001-patch-cm4.patch

git reset --hard 3a33f11c48572b9dd0fecac164b3990fc9234da8

git apply 0001-patch-cm4.patch

KERNEL=kernel8 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
KERNEL=kernel8 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j2

mkdir ./modules

rm -rf ./modules/*

INSTALL_MOD_PATH=./modules make modules_install

rm modules/lib/modules/*/build
rm modules/lib/modules/*/source

To break this down, the above commands cause the following to happen:

  • Download the Raspberry Pi branch of the Linux Kernel from their official repo
  • Go to an old commit, specifically one which is Kernel version 5.10.17
  • Apply a custom patch, provided by ClockworkPi, which alters part of the source (more about this below)
  • Compile the kernel

Essentially this means it is not possible to run any kernel other than 5.10.17 using these instructions. Further research and effort is required for the end user (me, in this situation) to get a new kernel.

The custom patch file

Before we can build a newer kernel, we need more information about the patch that ClockworkPi supplies. Looking through it, we can see that it adds the driver source code for the display used in 2 ClockworkPi devices (including the uConsole), configures some pin numbers for the Pi, configure the power management chip, and change some defaults for the Pi4.

The kernel build process uses a configuration file which can be generated using this command:

KERNEL=kernel8 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig 

This pulls in configuration from the bcm2711_defconfig file which contains good defaults for the Pi4. Weirdly, the patch provided by ClockworkPi doesn't include the manual changes made to this file and instead includes the final auto-generated config file. This means that the patch will almost never be compatible with any version aside from 5.10.17 only. Luckily this can be reverse engineered easily so we can use it on other versions.

I determined what changes they had (manually) made to their build config by generating the config using the vanilla 5.10.17 kernel and then the patched kernel. It gave me this output:

diff .config-linux .config-uconsole-working  

25c25 

< CONFIG_LOCALVERSION="-v8" 

--- 

> CONFIG_LOCALVERSION="-v8-JHEWITT" 

1853c1853 

< CONFIG_REGMAP_I2C=m 

--- 

> CONFIG_REGMAP_I2C=y 

2552,2554c2552,2554 

< CONFIG_PPP=m 

< CONFIG_PPP_BSDCOMP=m 

< CONFIG_PPP_DEFLATE=m 

--- 

> CONFIG_PPP=y 

> CONFIG_PPP_BSDCOMP=y 

> CONFIG_PPP_DEFLATE=y 

2556c2556 

< CONFIG_PPP_MPPE=m 

--- 

> CONFIG_PPP_MPPE=y 

2559,2560c2559,2560 

< CONFIG_PPPOE=m 

< # CONFIG_PPTP is not set 

--- 

> CONFIG_PPPOE=y 

> CONFIG_PPTP=m 

2562,2563c2562,2563 

< CONFIG_PPP_ASYNC=m 

< CONFIG_PPP_SYNC_TTY=m 

--- 

> CONFIG_PPP_ASYNC=y 

> CONFIG_PPP_SYNC_TTY=y 

2565c2565 

< CONFIG_SLHC=m 

--- 

> CONFIG_SLHC=y 

3032a3033 

> CONFIG_INPUT_AXP20X_PEK=y 

3251c3252 

< CONFIG_I2C_BCM2835=m 

--- 

> CONFIG_I2C_BCM2835=y 

3366a3368 

> # CONFIG_PINCTRL_AXP209 is not set 

3529a3532,3535 

> CONFIG_CHARGER_AXP20X=m 

> CONFIG_BATTERY_AXP20X=m 

> CONFIG_AXP20X_POWER=m 

> # CONFIG_AXP288_FUEL_GAUGE is not set 

3802c3808,3809 

< # CONFIG_MFD_AXP20X_I2C is not set 

--- 

> CONFIG_MFD_AXP20X=y 

> CONFIG_MFD_AXP20X_I2C=y 

3923a3931 

> CONFIG_REGULATOR_AXP20X=y 

4825a4834,4835 

> CONFIG_DRM_PANEL_CWD686=m 

> CONFIG_DRM_PANEL_CWU50=m 

4971a4982 

> CONFIG_BACKLIGHT_OCP8178=m 

6513a6525,6526 

> CONFIG_AXP20X_ADC=m 

> # CONFIG_AXP288_ADC is not set 

6535c6548 

< # CONFIG_TI_ADC081C is not set 

--- 

> CONFIG_TI_ADC081C=m 

7560c7573 

< CONFIG_CRYPTO_LIB_ARC4=m 

--- 

> CONFIG_CRYPTO_LIB_ARC4=y 

7616c7629 

< CONFIG_CRC_CCITT=m 

--- 

> CONFIG_CRC_CCITT=y 

Naturally the “JHEWITT” part was added by me, this was so I could differentiate the uConsole kernel with the vanilla kernel. The other changes were made by ClockworkPi.

There are some very unexpected changes here. Interestingly they made it so on their kernel some things related to VPNs and networking would be in the kernel rather than in modules. I'm not yet sure if or why this change is needed. The following parts are the most important (and the rest may or may not be important, still be to determined):

CONFIG_REGMAP_I2C=y 
CONFIG_INPUT_AXP20X_PEK=y 
CONFIG_CHARGER_AXP20X=m 
CONFIG_BATTERY_AXP20X=m 
CONFIG_AXP20X_POWER=m 
CONFIG_MFD_AXP20X=y 
CONFIG_MFD_AXP20X_I2C=y 
CONFIG_REGULATOR_AXP20X=y 
CONFIG_DRM_PANEL_CWU50=m 
CONFIG_BACKLIGHT_OCP8178=m 
CONFIG_AXP20X_ADC=m 
CONFIG_TI_ADC081C=m 
CONFIG_CRYPTO_LIB_ARC4=y 
CONFIG_CRC_CCITT=y 

This ensures the display driver is included in the kernel as a module, in addition to ensuring the kernel supports their other custom hardware. Note in the snippet above I removed the display for their Devterm device which is unused on the uConsole. It seems to make no difference at all whether or not this is included.

Pasting this text above into your bcm2711_defconfig file should cause the build process to ensure the important custom parts of the kernel are actually included when compiled.

Patching the source files

Also in the patch file were changes to various source files. I did the following in order to ensure all of the changes were included:

git apply --reject --whitespace=fix 0001-patch-cm4.patch 

This will work on any kernel version and create .rej files containing all of the merge conflicts. If the kernel maintainers edited part of the source which ClockworkPi also modified, you will need to manually choose what to keep (tip: you probably want to keep the ClockworkPi change unless you know what you are doing). I suggest also opening their patch alongside your editor to see what exactly they wanted the file to look like.

Luckily ClockworkPi did not make many changes to existing files, since most of their changes are in their own files. You should only see a few conflicts in .rej files and most of it is related to the Makefiles. If you are targeting a kernel that is not 5.10.17, you should revert their config file change with:

git checkout -- arch/arm64/configs/bcm2711_defconfig

Once you've done that, paste in the changes listed above (starting with CONFIG_XXXXXXX=) for your config in bcm2711_defconfig.

Ensure you delete each .rej file once you have addressed the conflict it is referring to.

In my experience compiling on 6.1 kernels, I ran into a compilation error in their display drivers. I made the following change which fixed the compilation but the resulting kernel has a non-functioning display now:

static int cwu50_remove(struct mipi_dsi_device *dsi)
{
	struct cwu50 *ctx = mipi_dsi_get_drvdata(dsi);

	mipi_dsi_detach(dsi);
	drm_panel_remove(&ctx->panel);

	return 0;
}

to this:

static void cwu50_remove(struct mipi_dsi_device *dsi)
{
        struct cwu50 *ctx = mipi_dsi_get_drvdata(dsi);

	mipi_dsi_detach(dsi);
	drm_panel_remove(&ctx->panel);

}

Kernel 5.10.x versions work fine and this file does not need to be changed unless you are targeting a kernel newer than 5.10, such as 6.1.

I made the same change to their other display (cwd686) but excluded it from some of my kernel builds. This display is not used on the uConsole and it doesn't seem to make a difference whether you include it or not.

How I compile the Kernel

I personally found the ClockworkPi instructions to be slightly lacking, so here's what I came up with:

These instructions are designed for Debian based distros.

  1. Install a fresh distro onto your SD card; preferably Raspberry Pi OS. I tested the latest version (2023-10-10, Kernel 6.1).
  2. Mount the SD card on your Linux machine, you should have 2 partitions available likely in /media/ which will be referred to rootfs (the ext4 partition) and bootfs (the fat32 partition)
  3. Run the following commands:

(If you did not already do so, edit bcm2711_defconfig to include something unique as the CONFIG_LOCALVERSION= value: it will show up in uname -a on your new OS so you can verify your kernel is running)

sudo apt install crossbuild-essential-arm64 build-essential gcc-aarch64-linux-gnu flex bison libncurses-dev libssl-dev libelf-dev

KERNEL=kernel8 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig 

make -j8 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs 

sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/media/user/rootfs/ modules_install

sudo cp arch/arm64/boot/Image /media/user/bootfs/kernel8.img 

sudo cp arch/arm64/boot/dts/broadcom/*.dtb /media/user/bootfs/

sudo cp arch/arm64/boot/dts/overlays/*.dtb* /media/user/bootfs/overlays/

sudo cp arch/arm64/boot/dts/overlays/README /media/user/bootfs/overlays/ 

Finally edit /media/bootfs/config.txt to match what ClockworkPi suggests, I use this:

disable_overscan=1
dtparam=audio=on
[pi4]
max_framebuffers=2

[all]
ignore_lcd=1
dtoverlay=dwc2,dr_mode=host
dtoverlay=vc4-kms-v3d-pi4,cma-384
dtoverlay=devterm-pmu
dtoverlay=devterm-panel-uc
dtoverlay=devterm-misc
dtoverlay=audremap,pins_12_13

dtparam=spi=on
gpio=10=ip,np

gpu_mem=128

I successfully used the information above to get Kernel 5.10.17 and 5.10.110 onto my fresh Raspberry Pi OS (2023-05-03-raspios-bullseye-arm64) but ran into issues with a 6.1 kernel. I am still working on finding the cause of the problem and will update this page when the problem is resolved.

Updated patch

I made an updated patch which you can use to make a 5.10.110 kernel. Follow the instructions above or as documented by ClockworkPi but use commit hash 8e1110a580887f4b82303b9354c25d7e2ff5860e and my patch.

That should let you easily compile a more modern kernel than what ClockworkPi officially supports without much more effort from you.

I will continue working on this so we can have a nicer way of building the kernel without resorting to patches based upon specific kernel versions.

uconsole.txt · Last modified: 2024/02/18 09:57 by joseph