Installing Debian on the K230-CanMV

As the first commercially available RISC-V development board with support for the (ratified version of the) RISC-V "V" Vector extension, Canaan's Kendryte K230 has gotten a lot of interest. As I am writing, boards from the second production batch are presumably in transport for those who preordered them. I was quick and lucky enough to order a board from the first batch, which arrived on October 31st 2023, so I have been able to tinker with it for over a month.

Official SDK

There are actually not one but two official SDKs:

The board is intended to be used for AI image processing, with a tiny busybox-based Linux system running on the little C908 core. Either an RTOS application or Python script runs on the big C908 core. Only the big core supports the Vector extension. It is also clocked at double the frequency of the little core.

The vendor does provide prebuilt version of the SDK, though the links are hard to find through the official SDK documentation. You can also rebuild it yourself although the build instructions are only available in simplified Chinese, and the build system is, to put it bluntly, awful.

Alternate K230 boot

With that noted, I did spend some time setting up a more robust and also much lighter-weight (you could even say barer bones) build system for just the bootloader and Linux kernel image. This also gets Linux running on the big core, with all 512 MiB of RAM and all of the microSD card disk space.

If you want to inspect it or even rebuild it, you can find the sources and further documentation here. There is still a lot of room for improvements, and help is most welcome.

But this lacks an operating system. So here is how to install the Debian, which officially supports 64-bit RISC-V as of earlier this year (2023).

Installing Debian

Prerequisites

To install Debian, we need a computer running Debian, Ubuntu or another derivative with Internet access, root privileges, and:

Note that the board is only needed at the end, so you can prepare your installation before you get your hands on it.

Preparation

Okay, so first the rather obvious first steps:

At this point, you need to ascertain very carefully the device node for the microSD card. Typically, this will be something like /dev/sdz (with another letter than z at the end) but it depends on the card drive. The following command lines use /dev/sdz but you need to substitute it for the actual path in your setup.

And then we need to get a root shell.

Flashing

  1. Install necessary tools:
    # apt-get install xz-utils parted debootstrap cu
  2. Unless you are using another RISC-V system, install user-mode QEMU:
    # apt-get install qemu-user-static binfmt-support
  3. Decompress the downloaded image:
    # unxz sysimage-sdcard.img.xz
  4. Flash the boot image (BEWARE the correct device node):
    # dd if=sysimage-sdcard.img of=/dev/sdz bs=1M conv=sync
  5. Start the disk partitioning tool:
    # parted /dev/sdz

Now you should see the GNU Parted prompt: (parted).

  1. Type the command resizepart to resize a partition.
  2. Agree to fix the GPT when asked (this occurs because the flashed image is much smaller than the SD card).
  3. Specify partition number 5.
  4. Select a size for the root filesystem. To use the full card capacity, you can specify -1. You should pick at least 1 GiB.
  5. Press Ctrl+D to exit Parted.

Overall, it should look something like this:

# parted /dev/sdz
GNU Parted 3.6
Using /dev/sdd
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) resizepart
Warning: Not all of the space available to /dev/sdz appears to be used, you can
fix the GPT to use all of the space (an extra 31087616 blocks) or continue with
the current setting?
Fix/Ignore? Fix
Partition number? 5
End?  [13,6MB]? -1
(parted)

Information: You may need to update /etc/fstab.

Bootstrapping Debian

The SD card is now bootable and partitioned properly. You are ready to install the operating system:

  1. Resize the root filesystem to adjust to its new partition size:
    # e2fsck -f /dev/sdz5
    # resize2fs /dev/sdz5
  2. Mount the root filesystem:
    # mkdir /mnt/root
    # mount /dev/sdz5 /mnt/root
  3. Bootstrap a Debian RISC-V root:
    # rm -Rf /mnt/root/sbin
    # debootstrap --arch=riscv64 unstable /mnt/root/
    You can optionally append the URL of a local Debian mirror to the above command line. It takes a while, so go grab a tea or coffee.
  4. Define a root password:
    # chroot /mnt/root
    # passwd #
    (enter the password twice after this)
    # exit
  5. Configure systemd not to start a login console on the SBI console (as it would conflict with the serial console):
    # ln -sf /dev/null /mnt/root/etc/systemd/system/serial-getty@hvc0.service
  6. Unmount the root filesystem:
    # umount /mnt/root

After the last umount command has completed succesfully, you can eject the microSD card.

First boot

  1. Plug the USB-C end of the USB cable in to the board's POWER port.
  2. Plug the USB-A end of the USB cable to a free USB port on the computer.
  3. A pair of USB ACM device (cdc_acm) should appear on the computer. Check the corresponding device nodes, typically ttyACM0 and ttyACM1.
  4. Attach to the first ACM device:
    cu -l ttyACM0
  5. Press the RST button (to the left of the POWER connector) on the board
  6. You should see this error message from the board:
    boot failed with exit code 19
  7. Insert the microSD card into the board's TF slot on the back side. Make sure it is properly fit.
  8. Press the RST button again.

You should now observe U-boot SPL, then U-boot proper, then OpenSBI, then the Linux kernel, and last but not least Debian, start up. Finally, you should get a login prompt.

  1. Login as root.
  2. Set (a good approximation of) the current time:
    # date -s @1718959020

Congratulations. Debian is now running and is ready for you to customise. You may want to start with:

To detach from the serial port, log out of the root shell then press tilde, then tilde again and lastly dot.

Troubleshooting

No carrier on the Ethernet adapter

This is a known issue (probably with a hardware defect). To work around this, disable auto-negotiation and force the Ethernet link speed to 10 MBits/s, e.g.:

ethtool -s eth0 autoneg off speed 10 duplex full

(If nothing else works, you may need to install ethtool using the chroot method as to set the root password).

HDMI not working

HDMI is meant to be driven by the RTOS. The vendor kernel does accordingly not provide the necessary Linux DRM drivers. So HDMI does not work. Somebody would need to write the necessary device drivers and extend the device tree. Patches welcome.

No access to I2C, PWM and/or GPIO

The situation is (presumably) more or less the same for HDMI, although it should be a lot less involved to fix. Again patches welcome.

WiFi

Status is unknown. I have only used wired Ethernet. Yet again, patches welcome.