Pine64 introduced the Ox64 recently. This board features a Bouffalo Lab BL808 MCU. Inside this MCU we’ve got 3 different cores. The core referred to as M0 is an RV32IMAFCP T-Head E907 core. The core referred to as D0 is an RV64IMAFCV T-Head C906 core, finally there is a core referred to as LP, which is an RV32EMC T-Head E902 core. In this chip we’ve got 64 MiB of RAM. The flash is external, and in case of my board, 16 MiB. There is also a 2MiB version, but I went for the largest option.

Now, a RV64IMAFCV core, that sounds like something that can run Linux. Let’s have a look. On the Bouffalo Lab github, there is a repo bl808_linux. This codebase appears to only compile with the gcc version they’ve linked in their documentation. It seems they use some extension that doesn’t exist or isn’t enabled in the gcc version for RISCV in the Arch Linux repo. But for now, let’s go ahead and use their version of gcc.

After building and flashing, I ran into a problem. That repo was made with a different board in mind. The pins they’re using for UART are not connected to pins on the Ox64 board. Patching it to different pins ain’t trivial as the code looks like:

		writel(0x00401502, (void *)0x200008e4); //IO8, TXD
		writel(0x00401517, (void *)0x200008d8); //IO5, RXD

The reference manual ain’t that useful, it seems not all registers are documented. I’ll have to go through the source code in the bl_mcu_sdk repo. If I were to do this, I would make a fork on github where I do my changes. Now, if anyone else would do this, they’d do the same, right? Now, there are 14 forks, so I went looking through them, and one of them had the UART patches in there: A fork by Zagitta. So, let’s go ahead with that fork. Building, uploading, and we’re booting.

So, how to build Linux and flash the Ox64? Let’s go!

To flash the board, we need to download “Bouffalo Lab Dev Cube” from Note that this is a GUI application, so flashing cannot be automated using this tool. There exist some console flasher for Bouffalo Lab chips, but this will need some more investigation.

Now, the said GUI tool is a bit iffy. It doesn’t seem to like my multi monitor setup much,

The pinout for the fork I am using, uses GPIO16 and GPIO17 for the Linux UART. These pins aren’t even marked as being UART pins on the official pinout.

1 (GPIO14) Programming Uart TX
2 (GPIO15) Programming Uart RX
30 (PU_CHIP) Reset Line
31 (GPIO17) Linux Uart RX
32 (GPIO16) Linux Uart TX

Put a breadboard wire on pin 30. This is the reset pin.

Start the Bouffalo Lab Dev Cube application. Please note, one might wish to disable secondary monitors, as my multi-monitor setup confuses the application. While the executable is called BLDevCube-ubuntu, it works fine on other distros, at least, it works on Arch.
Enter the “MCU” tab, Set “M0” to “group0”, set “D0” to “group1”, set the “Image Address” for both to “0x58000000”, browse to the build output directory where you compiled your code, and select “low_load_bl808_m0.bin” and “low_load_bl808_d0.bin” respectively.

Now, press the boot button on the board, and tap the USB connector with the breadboard wire to enter bootloader mode. Then click the “Create & Download” button.

After the flashing is complete, go to the “IOT” tab, and make sure “Enable” is elected at the “Single Download Options”, set the address to 0xD2000, then select the “whole_img_linux.bin” from the compilation output. Finally, click the “Create & Download” button again.

If you run into errors: Make sure you have entered bootloader mode, by using the breadboard wire to reset the MCU while holding the button on the board. Pressing the button while powering the board up is not sufficient. Furthermore, make sure nothing is connected to the JTAG pins (4,5,26,27). As the GPIO12/GPIO13, Pin 4,5, are marked UART on the schematic, I had an UART on there, which made flashing fail. Having a CKLINK debugger probe on there does not prevent the flashing to work.

Once flashing is done, have an UART bridge at GPIO16 and GPIO17, at 200Kbps, and you reset the board again. Then it should show the board booting Linux.

We now have the board booting, but it ain’t doing much useful yet. Next steps is seeing whether it is possible to get the RF (µSD) slot working. This probably would require writing drivers, looking at this github issue. In the Reference Manual is no documentation regarding SD at all. There is code in the bl_mcu_sdk repo… Oh well…

While I got Linux booting, at the moment it seems to be too incomplete to be usable. Furthermore, I have questions. How does it boot? What are these low_load files? Obviously it is one file for the “M0” core and one file for the “D0” core, but as I gave them both address “0x58000000”, how does that work? Is there some memory mapping going on from addresses on each core’s busses to the actual address in flash? It must be something like that. I’ve found these notes about the boot process. Some answers regarding the mapping procedure might be found in this article about the BL602.