Apache NuttX RTOS for Pine64 Ox64 64-bit RISC-V SBC (BouffaloLab BL808)
Find a file
2023-10-30 19:54:18 +08:00
.github Create FUNDING.yml 2023-10-28 16:37:00 +08:00
bl808-pine64-ox64.dtb Update doc 2023-10-28 21:00:49 +08:00
bl808-pine64-ox64.dts Update doc 2023-10-28 21:00:49 +08:00
LICENSE Initial commit 2023-10-28 16:34:51 +08:00
README.md Update doc 2023-10-30 19:54:18 +08:00

Apache NuttX RTOS for Pine64 Ox64 64-bit RISC-V SBC (BouffaloLab BL808)

What's this BL808? (Datasheet) (Reference Manual)

BL808 is a complex creature with 3 (Asymmetric) RISC-V Cores (linked via IPC)...

  1. D0 Core: T-Head C906 64-bit RV64IMAFCV (480 MHz)

    (Multimedia Core with MIPI CSI / DSI, Neural Proc Unit)

    (Memory Mgmt Unit is Sv39, 128/256/512 TLB table entry. Same as Star64?)

  2. M0 Core: T-Head E907 32-bit RV32IMAFCP (320 MHz)

    (Wireless + Peripherals Core with WiFi, BLE, BT, Zigbee, Audio)

  3. LP Core: T-Head E902 32-bit RV32E[M]C (150 MHz)

    (Low Power Core)

Pine64 Ox64 is the dev board for BL808C.

(BL808C supports MIPI CSI Cameras but not MIPI DSI Displays. Maybe someday we'll see BL808D for MIPI DSI Displays)

Is Ox64 BL808 an SBC? Or an MCU Board?

Technically Ox64 BL808 boots 64-bit RISC-V Linux (via MicroSD), so it feels like an SBC...

But Ox64 BL808 also feels like an MCU Board...

  • Form Factor is similar to MCU Board

  • Limited Memory: 64 MB of RAM, 128 Megabits (16 MB) of Flash Memory

  • UART Pins need a USB Serial Adapter for Flashing and Console I/O

  • M0 Wireless Core is 32-bit RISC-V MCU

Ox64 BL808 sounds a little tiny for 64-bit Linux?

Yeah 64-bit Linux runs with Limited RAM on the D0 Multimedia Core. But most Peripherals are hosted on the M0 Wireless Core: WiFi, BLE, BT, Zigbee, Audio, ...

So we flash M0 with a simple 32-bit RISC-V Firmware, to forward the Peripheral Interrupts from M0 to D0 Linux.

Here are the binaries loaded into D0 Multimedia Core and M0 Wireless Core, from buildroot_bouffalo...

  • d0_lowload_bl808_d0.bin: This is a very basic bootloader that loads opensbi, the kernel and dts files into ram

  • m0_lowload_bl808_m0.bin: This firmware runs on M0 and forwards interupts to the D0 for several peripherals

  • bl808-firmware.bin: A image containing OpenSBI, Uboot and uboot dtb files.

  • sdcard-*.tar.xz: A tarball containing the rootfs for the image to be flashed to the SD card

Perhaps Ox64 BL808 might run more efficiently with a tiny 64-bit RTOS.

Why Apache NuttX RTOS?

It might be interesting to run Apache NuttX RTOS on both the D0 Multimedia Core and the M0 Wireless Core. Then D0 and M0 can talk over OpenAMP (Asymmetric Multi-Processing).

Let's explore...

Flash OpenSBI and U-Boot Bootloader to Ox64 BL808

Before booting Linux on Ox64, we flash OpenSBI + U-Boot Bootloader to D0 Multimedia Core, and the Peripheral Interrupt Firmware to M0 Wireless Core. From buildroot_bouffalo:

  • d0_lowload_bl808_d0.bin: This is a very basic bootloader that loads opensbi, the kernel and dts files into ram

  • m0_lowload_bl808_m0.bin: This firmware runs on M0 and forwards interupts to the D0 for several peripherals

  • bl808-firmware.bin: A image containing OpenSBI, Uboot and uboot dtb files.

Here are the steps, based on the Official Flashing Instructions...

  1. We tested with Pine64 Woodpecker CH340G USB Serial Adapter on macOS x64.

    Warning: Some USB Serial Adapters WON'T WORK!

    Probably because we are connecting at 2 Mbps, which might be too fast for some USB Serial Adapters.

    (Like this CP2102, which shows garbled text at 2 Mbps)

  2. Connect a USB Serial Adapter to Ox64 Serial Console:

    • Serial Console TX is physical pin 32 / GPIO 16
    • Serial Console RX is physical pin 31 / GPIO 17
    • Remember to connect GND
    • Baud 2,000,000 (2 Mbps)

    Power up Ox64 via the Micro USB Port. Ox64 Green LED should light up.

    TODO: What do we see in USB Serial Terminal?

    If the text appears garbled, try a different USB Serial Adapter. (See above)

  3. Connect a USB Serial Adapter to Ox64 Flashing UART:

    • Flashing UART TX is physical pin 1 / GPIO 14
    • Flashing UART RX is physical pin 2 / GPIO 15
    • Remember to connect GND
    • Baud 2,000,000 (2 Mbps)

    Power up Ox64 via the Micro USB Port. Ox64 Green LED should light up.

    We should see the Ox64 Factory Test Firmware in the USB Serial Terminal...

    Simple Malloc 5120
    custom 0x0000
    flash init 0
    BLSP Boot2 start:Aug 25 2022,15:42:52
    Build Version: 3aa71dc-dirty
    Build Date: Sep 16 2022
    Build Time: 14:40:13
    [OS] Starting aos_loop_proc task...
    [OS] Starting OS Scheduler...
    [ERROR : bl_romfs.c: 129] romfs magic is NOT correct
    Init CLI with event Driven
    start aos loop... 
    CLI RAW Data, c906
    /romfs/c906.bin not found!
    

    (Source)

    If the text appears garbled, try a different USB Serial Adapter. (See above)

    TODO: Verify this on shipped version of Ox64

  4. Initial Check: Set BL808 board to programming mode

    • Press and Hold BOOT Button
    • Unplug and replug the Micro USB Port
    • Release BOOT button

    We should see this in the USB Serial Terminal...

    .
    

    Yep Ox64 is ready for flashing!

  5. Now we prepare to flash:

    Disconnect the USB Serial Terminal (to release the Flashing UART)

    Set BL808 board to programming mode

    • Press and Hold BOOT Button
    • Unplug and replug the Micro USB Port
    • Release BOOT button
  6. We download the Ox64 Binaries...

    From the latest Ox64 Linux Release...

    Unzip the download and we should see this...

    → ls -l firmware
       7340032  bl808-firmware.bin
         31360  d0_lowload_bl808_d0.bin
         65760  m0_lowload_bl808_m0.bin
    1820364800  sdcard-pine64_ox64_full_defconfig.img
      43859444  sdcard-pine64_ox64_full_defconfig.img.xz    
    
  7. We'll run BouffaloLab DevCube for Flashing BL808.

    Only Ubuntu x64, macOS and Windows are supported.

    TODO: How to flash BL808 on Arm64 SBCs and Pinebook Pro? See bflb-iot-tool / bflb-mcu-tool

  8. Get DevCube 1.8.3 from...

    openbouffalo.org/static-assets/bldevcube/BouffaloLabDevCube-v1.8.3.zip

    Normal download location is dev.bouffalolab.com/download but 1.8.4 and later do not work

    TODO: Does latest version work?

  9. Run DevCube, select [BL808], and switch to [MCU] page

  10. M0 Group[Group0] Image Addr [0x58000000] [PATH to m0_lowload_bl808_m0.bin]

  11. D0 Group[Group0] Image Addr [0x58100000] [PATH to d0_lowload_bl808_d0.bin]

  12. Click 'Create & Download' and wait until it's done

  13. Switch to [IOT] page

  14. Enable 'Single Download', set Address with 0x800000, choose [bl808-firmware.bin]

  15. Click 'Create & Download' again and wait until it's done

TODO: Does it work?

Boot Linux on Ox64 BL808

Now that D0 Multimedia Core is flashed with OpenSBI and U-Boot Bootloader, we're ready to boot Linux on microSD!

Based on the Official Flashing Instructions...

  1. Flash the sdcard-pine64-*.img.xz to your microSD card.

    You can use dd (after uncompressing) or Balena Etcher.

  2. Insert the microSD Card into Ox64.

    Unplug and replug the Micro USB Port.

  3. Connect USB Serial Adapter to Ox64 Serial Console:

    • Serial Console TX is physical pin 32 / GPIO 16
    • Serial Console RX is physical pin 31 / GPIO 17
    • Remember to connect GND
    • Baud 2,000,000 (2 Mbps)

    Power up Ox64 via the Micro USB Port. Ox64 Green LED should light up.

    TODO: What do we see in USB Serial Terminal?

Inspect the Linux Image for Ox64 BL808

Will Apache NuttX RTOS boot on Ox64 BL808?

Let's examine the Linux Kernel Image for Ox64, and we replicate the same format for NuttX. (Which is how we ported NuttX to 64-bit RISC-V Star64 JH7110 SBC)

We download the Ox64 Binaries...

From the latest Ox64 Linux Release...

Unzip it and mount the SD Card Image...

→ ls -l sdcard-pine64_ox64_full_defconfig     
-  13,154,816  Image
-       4,012  bl808-pine64-ox64.dtb
-       4,106  bl808-sipeed-m1s.dtb
-         350  boot-m1s.scr
-         352  boot-pine64.scr
-         352  boot.scr
d          96  extlinux

Dump the Image as hex...

→ hexdump sdcard-pine64_ox64_full_defconfig/Image
0000000 4d 5a 6f 10 20 08 01 00 00 00 20 00 00 00 00 00
0000010 00 80 cd 00 00 00 00 00 00 00 00 00 00 00 00 00
0000020 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000030 52 49 53 43 56 00 00 00 52 53 43 05 40 00 00 00

The Linux Kernel Image begins with this RISC-V Linux Image Header...

Here are the decoded bytes...

  1. code0: Executable code

    (4 bytes, offset 0x00)

    4d 5a 6f 10 
    
  2. code1: Executable code

    (4 bytes, offset 0x04)

    20 08 01 00 
    
  3. text_offset: Image load offset, little endian

    (8 bytes, offset 0x08)

    00 00 20 00 00 00 00 00
    
  4. image_size: Effective Image size, little endian

    (8 bytes, offset 0x10)

    00 80 cd 00 00 00 00 00
    
  5. flags: Kernel flags, little endian

    (8 bytes, offset 0x18)

    00 00 00 00 00 00 00 00
    
  6. version: Version of this header (MinL MinM . MajL MajM)

    (4 bytes, offset 0x20)

    02 00 00 00
    
  7. res1: Reserved

    (4 bytes, offset 0x24)

    00 00 00 00
    
  8. res2: Reserved

    (8 bytes, offset 0x28)

    00 00 00 00 00 00 00 00
    
  9. magic: Magic number, little endian, "RISCV\x00\x00\x00"

    (8 bytes, offset 0x30)

    52 49 53 43 56 00 00 00
    
  10. magic2: Magic number 2, little endian, "RSC\x05"

    (4 bytes, offset 0x38)

    52 53 43 05
    
  11. res3: Reserved for PE COFF offset

    (4 bytes, offset 0x3C)

    40 00 00 00
    

Our NuttX Kernel shall recreate this RISC-V Linux Image Header. (Total 0x40 bytes)

(Or U-Boot Bootloader might refuse to boot NuttX)

Header Values are exactly the same as Star64. (Except the Image Size and Executable Code, since the Jump Address is different)

Thus we simply reuse the code from NuttX Star64!

Linux Device Tree for Ox64 BL808

TODO: Dump the Device Tree

dtc \
  -o bl808-pine64-ox64.dts \
  -O dts \
  -I dtb \
  bl808-pine64-ox64.dtb

Here's the Decompiled Device Tree: bl808-pine64-ox64.dts

TODO: Transmit to UART3 at 0x30002000. Reuse the BL602 UART Driver for NuttX.

serial@30002000 {
  compatible = "bflb,bl808-uart";
  reg = <0x30002000 0x1000>;
  interrupts = <0x14 0x04>;
  clocks = <0x04>;
  status = "okay";
  phandle = <0x0a>;
};

(Source)

TODO: Forward the Interrupts from M0 Wireless Core to D0 Multimedia Core via Mailbox / IPC (Where are the addresses documented?)

mailbox@30005000 {
  compatible = "bflb,bl808-ipc";
  reg = <
    0x30005000 0x20 
    0x30005020 0x20 
    0x2000a800 0x20 
    0x2000a820 0x20
  >;
  interrupts = <0x36 0x04>;
  interrupt-controller;
  #interrupt-cells = <0x03>;
  #mbox-cells = <0x02>;
  status = "okay";
  phandle = <0x03>;
};

(Source)

TODO: Print Debug Logs with OpenSBI

Documentation for Ox64 BL808

From buildroot_bouffalo:

  • m0_lowload_bl808_m0.bin - This firmware runs on M0 and forwards interupts to the D0 for several peripherals
  • d0_lowload_bl808_d0.bin - This is a very basic bootloader that loads opensbi, the kernel and dts files into ram
  • bl808-firmware.bin - A image containing OpenSBI, Uboot and uboot dtb files.
  • sdcard-*.tar.xz - A tarball containing the rootfs for the image to be flashed to the SD card