Cross-compiling the kernel to include usb-serial support

I’ve spent the last couple days trying to compile the latest kernel to include the usb-serial module and today I’ve succeeded.

For those who need/want this feature (I am using mine as a headless hardware dev system, so I needed to be able to interact with FTDI/UART adapters, which requires this module) I did the following.

I tried to build on the board itself a few times, but I was getting failures related to pahole/dwarves, which research was indicating to me needed some downgrading to repair. Meanwhile, my versions of dwarves/pahole are the only ones available in the repos, so I had to cross-compile.

I made a vagrant system for this, using the generic/debian11 libvirt image. If you run Debian directly, you can do this on your host system. If you have some other host os, you may want to go the vagrant route. I won’t cover how this is done; I’ll assume you’ve gotten yourself into a modern Debian install (it’s needed to build the .deb files correctly via make) in one way or another before you begin the build.

You’ll want to follow the instructions posted here under “Updating the Linux Kernel in Image” section; with some key changes.

First, once you’ve cloned the repository in the document, you’ll want to checkout a specific branch:

git checkout origin/JH7110_VisionFive2_devel
git switch -c JH7110_VisionFive2_devel

In addition to the packages in the documentation, you’ll want to install the riscv64 compile toolchain:

sudo apt install -y gcc-riscv64-linux-gnu

Then you can go about Cross-compiling to riscv by doing the following (do all of this as root, by the way, and set root as the owner of the files in the repo with chown -Rv 0:0 /path/to/repo):

cp arch/riscv/configs/starfive_visionfive2_defconfig .config
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- olddefconfig

After running make olddefconfig, you’ll want to edit this new .config file. Search for CONFIG_USB_SERIAL. You won’t find it before running the olddefconfig make command, so do that first. You’ll find it in a comment, reading # CONFIG_USB_SERIAL is not set. You can also just add the variables below before running make olddefconfig for the first time.

Change this to CONFIG_USB_SERIAL=m and add below it a line that says CONFIG_USB_SERIAL_GENERIC=y (this can not be built as a module, just say y).

After that, save the file, re-run the olddefconfig make command again, then re-enter the file and search for CONFIG_USB_SERIAL again. You’ll see a wide range of different options that start with CONFIG_USB_SERIAL_*, referring to specific devices. Change all of these from comments saying is not set to =m

Here that section of my file:

CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_SIMPLE=m
CONFIG_USB_SERIAL_AIRCABLE=m
CONFIG_USB_SERIAL_ARK3116=m
CONFIG_USB_SERIAL_BELKIN=m
CONFIG_USB_SERIAL_CH341=m
CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_VISOR=m
CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_EDGEPORT_TI=m
CONFIG_USB_SERIAL_F81232=m
CONFIG_USB_SERIAL_F8153X=m
CONFIG_USB_SERIAL_GARMIN=m
CONFIG_USB_SERIAL_IPW=m
CONFIG_USB_SERIAL_IUU=m
CONFIG_USB_SERIAL_KEYSPAN_PDA=m
CONFIG_USB_SERIAL_KEYSPAN=m
CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_METRO=m
CONFIG_USB_SERIAL_MOS7720=m
CONFIG_USB_SERIAL_MOS7840=m
CONFIG_USB_SERIAL_MXUPORT=m
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_OTI6858=m
CONFIG_USB_SERIAL_QCAUX=m
CONFIG_USB_SERIAL_QUALCOMM=m
CONFIG_USB_SERIAL_SPCP8X5=m
CONFIG_USB_SERIAL_SAFE=m
# CONFIG_USB_SERIAL_SAFE_PADDED is not set
CONFIG_USB_SERIAL_SIERRAWIRELESS=m
CONFIG_USB_SERIAL_SYMBOL=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_WWAN=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OMNINET=m
CONFIG_USB_SERIAL_OPTICON=m
CONFIG_USB_SERIAL_XSENS_MT=m
CONFIG_USB_SERIAL_WISHBONE=m
CONFIG_USB_SERIAL_SSU100=m
CONFIG_USB_SERIAL_QT2=m
CONFIG_USB_SERIAL_UPD78F0730=m
CONFIG_USB_SERIAL_XR=m
CONFIG_USB_SERIAL_DEBUG=m

That safe padded option that’s not set seems to have appeared after a third run of make olddepconfig and, whatever it does, it hasn’t broken anything for me so I’m not gonna rebuild the kernel.

Now to actually cross-compile the thing:

make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j $(nproc) bindeb-pkg

This will generate three .deb packages that you can transfer to and install on the board. When you reboot, it should present the 6.0.0.2 kernel (at time of writing, this branch is in-development obviously and may change. Current date is 2023-05-18. You may need to modify these instructions, or they may become obsolete as these features become standard with provided kernels.)

These are linux-image-{kernel-info}.deb, linux-headers-{kernel-info}.deb, and linux-libc-dev_{kernel-info}.deb.

After installing these on your system, don’t forget to update the contents of /boot/dtbs/* from the newly created /usr/lib/linux-image-{kernel-info}/* to update the device tree before reboot.

If you have trouble booting into your new kernel, you can get back into the original via uart. The system adds and removes boot entries pretty reliably. Check /boot/extlinux/extlinux.conf to modify boot entries.

Afterwards I can plug in my muArt and other FTDI adapters and see /dev/ttyUSB* devices. I see them present using the usbserial module in dmesg, and I’m able to interact with all my dev boards from these adapters successfully.

Hope this helps someone!

Much obliged,
MagusMycelius

2 Likes

FYI: You may also be able to access the running kernel config on a system (but only if the kernel was compiled with CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC), by using something like the following:

mzs@tock:~ $ zcat /proc/config.gz | grep PPS
gzip: /proc/config.gz: No such file or directory
mzs@tock:~ $ sudo modprobe configs
mzs@tock:~ $ zcat /proc/config.gz | grep PPS
CONFIG_PPS=y
# CONFIG_PPS_DEBUG is not set
# PPS clients support
# CONFIG_PPS_CLIENT_KTIMER is not set
CONFIG_PPS_CLIENT_LDISC=m
CONFIG_PPS_CLIENT_GPIO=m
# PPS generators support
mzs@tock:~ $ sudo modprobe -r configs

(can also be accessed as /proc/.config)

Some distributions put copy of the config used in /boot

1 Like

Thank you for the added insights! Very helpful!