cjacker / opensource-toolchain-bouffalo-lab

Opensource toolchain for BL602/BL604, BL702/BL704/BL706, BL616/BL618, BL808 and other series of RISC-V based chips from Bouffalo Lab
MIT License
15 stars 2 forks source link

Opensource toolchain for series RISC-V based MCU from Bouffalo Lab

Bouffalo Lab Intelligent Technology (Nanjing) Co., Ltd. was established in Nanjing in 2016. It is a company focusing on the research and development of world-leading ultra-low power consumption, intelligent Internet of Things and edge computing SoCs, as well as providing overall solutions for intelligent cloud platforms. enterprise. At the same time, the company has complete multi-mode wireless connection technology, audio and video processing and artificial intelligence algorithm technology, which can fully realize the chip research and development of single-chip integration.

In short, this company produce a series RISC-V based MCU which focused on Wi-Fi, BT, BLE, Zigbee, includes:

All datasheets and user manuals can be found in bl_docs repo.

This tutorial will try best to cover all these chips.

Table of contents

Hardware prerequist:

Toolchain overview:

NOTE 1:

About the difference between bl_iot_sdk & bouffalo_sdk, there is an answer here.

The answer is not very clear. In short, bl_iot_sdk focused on IOT-related programming, such as Wi-Fi/BLE, etc, and bouffalo_sdk didn't have these support before.

According to the comment from upstream : https://github.com/bouffalolab/bouffalo_sdk/issues/115

Iot sdk does not update at all, please use mcu sdk (it will be named bouffalosdk)

You should use bouffalo_sdk or M1s_BL808_SDK for Sipeed M1s Dock from now.

NOTE 2:

BLFlashCommand and BLFlashCube is close source software up to now. If this is a issue for you, you should know that.

NOTE 3:

bouffalo_sdk was originally named as bl_mcu_sdk and renamed to bouffalo_sdk recently.

Compiler

Not like usual RISC-V based MCU (such as CH32V / GD32V, etc), the toolchain setup for BL chips is a little bit complex. Different cores and Different SDKs may requires different toolchains.

For BL60x/70x, it's 32bit RISC-V MCU, as usual RISC-V MCU, it require RISC-V toolchain to generate 32bit object code.

For BL616, bouffalo_sdk set -mtune to e907, it can not supported by general RISC-V toolchain, you had to use T-Head RISC-V toolchain. Or you need change the -mtune=e907 to -mtune=size and will lost some optimizations when compiling.

For BL808, it has 3 different cores: two 32bit RISCV-V MCU (M0 / LP), one general purpose 64bit CPU (D0, based on T-Head C906). Since D0 core has MMU, that means it can run baremetal or run Linux OS, it need setup 3 toolchains:

You may already find some 'riscv64-unknown-elf' toolchains could work with 32bit RISC-V mcu, just like x86_64 toolchain, it can generate object codes for x86 and x86_64, so we can reduce toolchains to 2:

Usually I prefer to use Xpack prebuilt RISC-V toolchains, but Xpack only provide rv32 embed toolchain up to now and not compatible with Xuantie extentions. In this tutorial, we will and have to use prebuilt T-Head Xuantie toolchains.

T-Head Xuantie RISC-V embeded gcc

T-Head provide RISC-V embed toolchain (gcc v10.2.0) to work with 32bit and 64bit RISC-V, it can be download from here.

After download:

sudo mkdir -p /opt/xuantie-riscv64-embed-toolchain
sudo tar xf Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1-20220906.tar.gz -C /opt/xuantie-riscv64-embed-toolchain --strip-components=1

and add /opt/xuantie-riscv64-embed-toolchain/bin to PATH env according to your shell.

NOTE, the triplet of prebuilt Xuantie rv64 embed toolchain is riscv64-unknown-elf, make sure it is not conflict with other toolchains you already installed.

T-Head XuanTie RISC-V linux gcc [Optional]

You need this toolchain to build and run Linux kernel, and this section can be ignored now.

T-Head provide pre-built RISC-V 64bit linux toolchain (gcc v10.2.0), it can be download from here.

After download:

sudo mkdir -p /opt/xuantie-riscv64-linux-toolchain
sudo tar xf Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz -C /opt/xuantie-riscv64-linux-toolchain --strip-components=1

and add /opt/xuantie-riscv64-linux-toolchain/bin to PATH env according to your shell.

NOTE 1 : the triplet of prebuilt Xuantie linux toolchain is riscv64-unknown-linux-gnu. NOTE 2 : the sysroot is at '/opt/xuantie-riscv64-linux-toolchain/sysroot'.

Above toolchain setup is also suite for M1s_BL808_SDK.

SDK

bouffalo_sdk

bouffalo_sdk is a MCU software development kit provided by Bouffalo Lab, supports all the series of Bouffalo chips, include but not limited to:

SDK installation

The installation of bouffalo_sdk is very simple, just git clone and put it somewhere, for example:

git clone https://github.com/bouffalolab/bouffalo_sdk.git
# move it to home dir if not, you should have write permission to sdk dir.
mv bouffalo_sdk <where your home dir>

And, set env to export BL_SDK_BASE:

export BL_SDK_BASE=<path to>/bouffalo_sdk

'Out of SDK' building will use this env var to find bouffalo_sdk.

Demo project

The bouffalo_sdk use 'cmake' and 'make' to manage whole project, use blink demos in this repo as example, the dir structure looks like:

demo dir
├── CMakeLists.txt : manage sources list, build flags and target name.
├── flash_prog_cfg.ini : config file for BLFlashCommand.
├── main.c : source file(s).
├── Makefile : define CHIP/BOARD name, toolchain prefix, SDK PATH, etc. used to invoke the building process.
├── proj.conf : project specific CMAKE flags
└── readme.md

Blink Demo for BL702

Here use 'blink_bl702' demo with Sipeed RV Debugger Plus, 'blink_bl602' and 'blink_bl616' demo is almost same.

cd blink_bl702
make

If you did not export BL_SDK_BASE env var before, an error will happen here.

Please look at the contents of 'Makefile' to figure out how to define 'CHIP', 'BOARD' etc.

NOTE for Sipeed M0P BL618

You should use bl616 demos With Sipeed M0P Dock (BL618), but a patch need to be applied to bouffalo_sdk first.

cat ./blink_bl616/bouffalo_sdk-patch-for-m0p.patch |patch -p1 -d <where your bouffalo_sdk>

Triple Core Demo for BL808

Here use 'triplecore_bl808' example with Sipeed M1S Dock, This demo illustrates how to enable all 3 cores of BL808 and receive hello world msg from M0 / D0 and LP cores.

The patch to enable LP core I made for bouffalo_sdk was already upstreamed.

I put bouffalo_sdk at home dir, if you not, change this line in Makefile to your sdk path:

make -C $@ BL_SDK_BASE=$(HOME)/bouffalo_sdk

And type make directly.

After build successfully, these three firmware files will be generated:

For more infomation about how to use this tripple core demo, please refer to : https://github.com/cjacker/opensource-toolchain-bouffalo-lab/tree/main/triplecore_bl808

If you want to start a new project, you can either copy these demos from this repo, or use various demos in bouffalo_sdk/examples dir.

M1s_BL808_SDK

For Sipeed M1s, you can use bouffalo_sdk without any problem. But Sipeed M1s_BL808_SDK provide more features that bouffalo_sdk lacks now, for example, M1s_BL808_SDK has freertos / wifi / video / blai support that bouffalo_sdk don't have (for now). And the project management styles of bouffalo_sdk and M1s_BL808_SDK also differ a lot.

For Sipeed M1s dock, It's more convenient to use 'M1s_BL808_SDK' instead of 'bouffalo_sdk'.

The installation of M1s_BL808_SDK is very simple:

mkdir m1s && cd m1s
git clone https://github.com/sipeed/M1s_BL808_SDK.git
git clone https://github.com/sipeed/M1s_BL808_example.git

After git cloned, you should export an env var as export BL_SDK_PATH=<path to>/M1s_BL808_SDK, and change M1s_BL808_SDK/make_scripts_thead_riscv/toolchain.mk from

CONFIG_TOOLPREFIX ?= $(BL_SDK_PATH)/toolchain/$(shell uname |cut -d '_' -f1)_$(shell uname -m)/bin/riscv64-unknown-elf-

to

CONFIG_TOOLPREFIX ?= riscv64-unknown-elf-

Then build a demo using build.sh <demo dirname>:

cd M1s_BL808_example/c906_app
./build.sh lvgl_demo

After built successfully, 'lvgl_demo.bin' and 'lvgl_demo.elf' should be generated at build_out dir.

There is a warning 'mis-matched ISA version 1.0 for 'v' extension, the output version is 2.0' when link to some prebuilt binary libraries, such as 'libblai_npu_encoder.a', it can not fixed since 'libblai_npu_encoder.a' built with a private toolchain and it's safe to ignore it now.

Programming

There are tooooo many official programming tools for BL chips:

I know it may be a little bit confusing, I was also confused at first.

Usually, it's not neccesary for you to figure out the differences between all this programming tools and to decide which one you should use. If you use bouffalo_sdk, just use 'make flash' directly.

NOTE:

You can ignore this note

After BLFlashCommand commited into official bouffalo_sdk repo and with this commit [update][board] enable fw header for new flash tool :

Compare with old firmware before this commit, the final ELF has a section '.fw_header' prepended, it is so called 'bootheader'. you can use 'readelf -S build/build_out/xxx.elf' to verify it has a '.fw_header' section or not:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .fw_header0       PROGBITS        57fff000 001000 000160 00  WA  0   0  4
  ...

A script check-bootheader.sh at misc dir can be used to check whether bin file has a bootheader or not.

If you want to strip the "fw_header0" section from final 'bin' file, you should strip the first 4k as:

tail -c +4097 new_firmware_format.bin >old_firmware_format.bin

Such stripped firmware can be programmed by 'bflb-mcu-tool' to '0xN2000' again.

Programming tools installation

'BLDevCube' can be downloaded from : https://dev.bouffalolab.com/download

mkdir bldevcube
wget https://dev.bouffalolab.com/media/upload/download/BouffaloLabDevCube-v1.8.3.zip -P devcube
cd bldevcube
unzip BouffaloLabDevCube-v1.8.3.zip
chmod +x BLDevCube-ubuntu
chmod +x bflb_iot_tool-ubuntu

Actually, these tools are written in Python and packaged by pyinstaller, you can depackage and decompile them...

'BLFlashCommand' and 'BLFlashCube' are already integreated into 'bl_mcu_ask', there is no additional installation required, it's also written in Python and packaged by pyinstaller.

'bflb-mcu-tool' is written in python and open source, install it as:

pip install bflb-mcu-tool

'bflb-iot-tool' is written in python and open source too, you can use the pyinstalled-packaged one released with BLDevCube or install is as:

pip install bflb-iot-tool

And you should add $HOME/.local/bin to PATH env to find bflb-mcu-tool / bflb-iot-tool command.

blisp is written by Pine64 community, currently it can support BL60x and BL70x, and lack support for BL616 and BL808, but still worth a try. to build and install it:

git clone --recursive https://github.com/pine64/blisp.git
cd blisp
git submodule update --init --recursive
mkdir build && cd build
cmake -DBLISP_BUILD_CLI=ON ..
cmake --build .

Programming

for bouffalo_sdk

To program BL chips, you need enter UART programming mode first.

In short, if devboard has 'BOOT' button, "hold BOOT button down and power it" will enter UART programming mode (Except Sipeed M0Sense), actually it equals to "hold BOOT button down and click RESET button".

Then you can program it with make flash, it will invoke 'BLFlashCommand' to program BL chips.

BLFlashCommand read 'flash_prog_cfg.ini' as config file, please setup this file correctly.

All demos in this repo can be programmed by 'BLFlashComand', With various demos in this repo, just type:

make flash

You may need to set 'BL_SDK_BASE' to your bouffalo_sdk dir if using 'out sdk build'.

Update Mar 7 2023 : Finally I decided to remove all contents about how to use 'bflb-mcu-tool' / 'bflb-iot-tool' and 'blisp', it make things complex, the best way to program firmwares built with bouffalo_sdk is 'make flash'. it is more simpler for beginners.

for M1s_BL808_SDK

Beside BL808, Sipeed M1S Dock also have a standalone BL702 chip integrated on board to emulate 2 UART interfaces. you may need to:

         +--------------+                  +----------------+
         |OTP TypeC Port|                  |UART TypeC Port |
         +--------------+                  +----------------+
                |                              |        |
                |                              |        |
         +------V-------+                      V        V
         |3M USB storage|               +---------------------+
         |to program D0 |               | BL702,emulate 2 UART| <- to program BL702,
         |              |               |   +-----+  +-----+  |    hold 'BOOT' button and power it.
         |Hold S1+S2    |               |   |UART0|  |UART1|  |
         |Toggle 'RST'  |               |   +---^-+  +-^---+  |
         |Mount         |               +-------|------|---|--+
         +----+---------+                     RX|TX  RX|TX | <- to program BL808 by UART Mode, power it and
              |                                 |      |   |    hold 'BOOT' button, toggle 'RST'.
              |To program      +----------------|------|---+----------+
              |D0 Core         |  BL808         |      |              |
              |by Udisk mode   |        +-------V-+  +-V-------+      |
              +-------------------------> D0 Core |  | M0 Core |      |
     +------------+            |        +---------+  +---------+      |
     | Standalone |           D18 (TX)  +---------+                   |
     |UART adapter|<--------------------> LP Core |                   |
     |   UART2    |           D19 (RX)  +---------+                   |
     +------------+            +--------------------------------------+

You can use 'BLDevCube' Linux version to make things easier (but not easy for me), Sipeed already have a good tutorial here, please refer to sipeed tutorial on how to use 'BLDevCube' to program M1S Dock.

Here will explain how to program M1s Dock from command line:

To program on-board BL702 of M1S Dock

Usually, it's useful to fix or restore the factory 'dualuart' firmware.

You need activate BL702 UART programming mode first and :

$ bflb-iot-tool --chipname=bl702 --port=/dev/ttyACM0 --baudrate=2000000 --firmware=<dualuart factory firmware> --addr 0x2000 

To program E907 core of M1S Dock

You need activate BL808 UART programming mode first.

And use the bigger number of 2 serial devices, here is '/dev/ttyUSB1'.

bflb-iot-tool --chipname=bl808 --port=/dev/ttyUSB1 --baudrate=2000000 --pt=partition_cfg_16M_m1sdock.toml --boot2=boot2_isp_debug.bin --firmware=<m0 firmware.bin> 

Partion table and boot2 file had been put into m1s_factory_firmware copy dir in this repo. you can also find them from https://github.com/sipeed/M1s_BL808_example and BLDevCube.

To program C906 core of BL808 for M1S Dock

Option 1 : with U-Disk mode (M1S Specific)

M1S dock implement U-Disk programming mode for C906 core, to activate U-Disk programming mode:

It will programmed automatically and reset the device.

Option 2 : with bflb-iot-tool from commandline

I prefer this way, it's more convenient than U-Disk mode.

All factory demo firmwares for D0 or firmwares you build from M1S SDK can be programmed this way, After UART programming mode activated :

bflb-iot-tool --chipname=bl808 --port=/dev/ttyUSB1 --baudrate=2000000 --firmware=<firmware file> --addr 0x101000 --single

NOTE --addr 0x101000, since all factory demo firmwares for D0 and firmwares build from M1S SDK did not include 4k bootinfo (0x1000) at the start of bin file. Here use --addr 0x101000 to avoid replace bootinfo programmed by factory firmware.

For example, using 'lvgl_demo', it can be programmed as :

bflb-iot-tool --chipname=bl808 --port=/dev/ttyUSB1 --baudrate=2000000 --firmware=build_out/lvgl_demo.bin --addr 0x101000 --single

A script 03-program-d0-firmware.sh provided in m1s_dock_factory_firmware, you can use this script directly to program your own D0 firmware for M1S Dock if you use 'M1s_BL808_SDK'.

Debugging

Debugging of BL series chips are supported by OpenOCD with JTAG debugger or C-Sky Debug Server with CK-Link debugger.

The pinmaps of JTAG or CK-Link are same as below table:

CHIP/Pin BL602/BL604 BL702/BL704/BL706 BL616/BL618 BL808
TMS GPIO12 GPIO0 GPIO0 GPIO6
TCK GPIO14 GPIO2 GPIO1 GPIO12
TDO GPIO11 GPIO9 GPIO2 GPIO7
TDI GPIO17 GPIO1 GPIO3 GPIO13

With OpenOCD and JTAG debugger

There are some target config for OpenOCD in bouffalo_sdk, you can use them directly:

Not like STM32, OpenOCD can NOT program BL chips directly. Before debugging codes run in flash with OpenOCD, you have to program the target device using UART ISP mode.

After target device programmed, wire up any JTAG adapter as above table with target device, and launch RISC-V OpenOCD as:

riscv-openocd -f <interface config file> -f tgt_702.cfg

The 'interface config file' depends on which jtag debugger you use.

If everything OK, the output looks like:

Info : clock speed 4000 kHz
Info : JTAG tap: riscv.cpu tap/device found: 0x20000e05 (mfg: 0x702 (<unknown>), part: 0x0000, ver: 0x2)
Info : [riscv.cpu.0] datacount=1 progbufsize=2
Info : Disabling abstract command reads from CSRs.
Info : Disabling abstract command writes to CSRs.
Info : [riscv.cpu.0] Examined RISC-V core; found 1 harts
Info : [riscv.cpu.0]  XLEN=32, misa=0x40801125
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : JTAG tap: riscv.cpu tap/device found: 0x20000e05 (mfg: 0x702 (<unknown>), part: 0x0000, ver: 0x2)
reset-assert-pre
reset-deassert-post
reset-init
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Then open another terminal window and run gdb as:

riscv64-unknown-elf-gdb build/build_out/blink_bl702.elf

After '(gdb)' prompt showed:

(gdb) target remote :3333
Remote debugging using :3333
...
(gdb) set $pc=0x21000000
(gdb) set $mie=0x00
(gdb) set $mstatus=0x1880
(gdb) list main 15
15          while (1) {
16              bflb_gpio_set(gpio, GPIO_PIN_25);
17              bflb_mtimer_delay_ms(200);
18              bflb_gpio_reset(gpio, GPIO_PIN_25);
19              bflb_mtimer_delay_ms(200);
20          }
21      }
(gdb) hb 17
Hardware assisted breakpoint 1 at 0x2300238e: file <path>/blink_bl702/main.c, line 17.
(gdb) c
Continuing.

Breakpoint 1, main () at <path>/blink_bl702/main.c:17
17              bflb_mtimer_delay_ms(200);
(gdb)

There are something need to be explained here:

For the code running on XIP, load is unnecessary and cannot be used, because XIP programs need to be programmed with a programming tool before debugging, and writing to the XIP area may cause unknown errors. In addition, the XIP program needs to rely on ROM code (0x21000000) to initialize the related software and hardware, so the following configuration is required:

set $pc = 0x21000000

set $mie = 0

set $mstatus = 0x1880

For more infomation about OpenOCD and gdb usage, please refer to official document "Introduction of OpenOCD and GDB.pdf".

With C-Sky debug server and CK-Link Lite

You can buy a T-Head or HLK CK-Link Lite debugger from Aliexpress (a little bit expensive), or make it yourself using Sipeed RV Debugger plus / Sipeed M0S Dock or STM32F103 blue pill.

Install C-Sky debug server

The T-Head debug server can be downlowed from https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1673423345494/T-Head-DebugServer-linux-x86_64-V5.16.7-20230109.sh.tar.gz

After download finished:

tar xf T-Head-DebugServer-linux-x86_64-V5.16.7-20230109.sh.tar.gz
tail -n +282 T-Head-DebugServer-linux-x86_64-V5.16.7-20230109.sh >csky-debug-server.tar.gz

Then extract the 'csky-debug-server.tar.gz' to somewhere, for example:

mkdir -p /opt/csky-debug-server
sudo tar zxf csky-debug-server.tar.gz -C /opt/csky-debug-server

The command of csky-debug-server is DebugServerConsole.elf, it depend on some libraries installed at /opt/csky-debug-server dir,you have to run it as:

cd /opt/csky-debug-server
./DebugServerConsole.elf

Or

LD_LIBRARY_PATH=/opt/csky-debug-server /opt/csky-debug-server/DebugServerConsole.elf

You can save below wrapper script as csky-debug-server and put it to /usr/bin:

#!/usr/bin/bash
cd /opt/csky-debug-server
export LD_LIBRARY_PATH=/opt/csky-debug-server
./DebugServerConsole.elf $@

You may also need to create a udev rule '/etc/udev/rules.d/99-csky-cklink.rules' with below contents to set device permission correctly (allow normal user read / write the CK-Link device).

# For Hi-Link CK-Link lite
SUBSYSTEM=="usb", ATTR{idVendor}="32bf", ATTR{idProduct}=="b210", MODE="666"
# For Sipeed
SUBSYSTEM=="usb", ATTR{idVendor}="42bf", ATTR{idProduct}=="b210", MODE="666"

After this udev rules saved, please run:

udevadm trigger
udevadm control --reload

Option 1 : Use T-Head or HLK CK-Link debugger

The Ck-Link pinout:

 +-------------+
 | TDI ▪ • GND |
 | TDO • • GND |
   TCK • • GND |
    -- • • --  |
  nRST • • TMS |
 |  -- • • --  |
 |VREF • • TRST|
 +-------------+

Official CK-Link debugger from T-Head or HLK doesn't supply power to target board, you need supply power to target board with another USB cable seperately.

Option 2 : Use Sipeed RV Debugger Plus or M0S Dock with cklink-lite firmware

The cklink-lite firmware for RV Debugger Plus and M0S Dock are provided in this repo:

To program Sipeed RV Debugger Plus, hold 'BOOT' down and plug it in PC USB port:

cd sipeed_rv_debugger_plus_factory_firmware
./01-program-cklink-lite.sh

The pinmap was already printed at the back of Sipeed RV Debugger Plus:

To program Sipeed M0S Dock, hold 'BOOT' down and plug it in PC USB port:

cd m0s_dock_cklink-lite_firmware
./01-program-cklink-lite.sh

You need refer to below table for M0S Dock (as same as Sipeed RV Debugger Plus), since at the back of M0S Dock, only 'IOxx' is printed.

M0S Dock CK-Link pinout
GND GND GND GND
5V
3V3 5V 3V3
IO10 IO11 TCK TXD
IO12 IO13 TDI RXD
IO14 IO15 TDO DTR
IO16 IO17 TMS RTS

After programmed, re-power it and using lsusb, you will find:

42bf:b210 Bouffalo C-Sky CKLink-Lite

Then connect the target board with RV Debugger Plus / M0S Dock as same as CK-Link Lite Debugger.

Option 3 : Make your own CK-Link Lite debugger with STM32F103

C-Sky debug server contains a set of cklink firmware files, if you have a STM32F103 devboard, you can use 'cklink_lite.hex' shipped with C-Sky debug server to make your own CK-Link debugger.

'cklink_lite_iap.hex' (address range from 0x0800_0000 to 0x0800_4000) is the bootloader and 'cklink_lite.hex' (address range start from 0x0800_4000) is the firmware. the IAP firmware not works with STM32F103 bluepill (due to the circuit differences between CKLink Lite debugger and STM32F103 bluepill), we need modify the 'cklink_lite.hex' first to copy the vector table to the beginning of the flash:

I wrote a script to convert it automatically, you can find it in cklink-lite-fw-convertor repo.

And the pre-converted 'cklink-lite-2.36_for-stm32f103.hex can programmed to STM32F103 directly. If the firmware version is outdated, you can use cklink-lite-fw-convertor to convert the latest firmware yourself.

After STM32F103 programmed, refer to below table to connect STM32F103 with your target devboard and plug STM32F103 to PC USB port.

STM32F103 CK-Link
A0 TRST
A1 TCK
A4 TDO
A5 TMS
B9 TDI
3V3 3V3
GND GND

Launch C-Sky debug server

Then invoke C-Sky debug server as mentioned above:

# here I use wrapper script
csky-debug-server

If all good, the output looks like:

+---                                                    ---+
|  T-Head Debugger Server (Build: Jan  9 2023, Linux)      |
   User   Layer Version : 5.16.07
   Target Layer version : 2.0
|  Copyright (C) 2022 T-HEAD Semiconductor Co.,Ltd.        |
+---                                                    ---+
T-HEAD: CKLink_Lite_V2, App_ver 2.36, Bit_ver null, Clock 2526.316KHz,
       5-wire, With DDC, Cache Flush On, SN CKLink_Lite_V2-650763C7D6.
+--  Debug Arch is RVDM.  --+
+--  CPU 0  --+
RISCV CPU Info:
        MARCHID: 0x00000000
        MISA   : 0x40801125
Target Chip Info:
        HWBKPT number is 4, HWWP number is 4.
        MISA: (RV32IMAFCX, Imp M-mode)

GDB connection command for CPUs(CPU0):
        target remote 127.0.0.1:1025
        target remote xxx.xxx.xxx.xxx:1025

****************  DebuggerServer Commands List **************
help/h
        Show help informations.
*************************************************************
DebuggerServer$

Debugging

Use blink_bl702 as example, After build successfully, open new terminal window, and run:

riscv64-unknown-elf-gdb build/build_out/blink_bl702.elf

After '(gdb)' prompt showed:

(gdb) target remote :1025
Remote debugging using :1025
main () at /home/cjacker/work/opensource-toolchain-bouffalo-lab/blink_bl702/main.c:18
18              bflb_gpio_reset(gpio, GPIO_PIN_25);
(gdb) b main
Breakpoint 1 at 0x23002350: file /home/cjacker/work/opensource-toolchain-bouffalo-lab/blink_bl702/main.c, line 9.
(gdb) c

Build and run openbouffalo Linux Image for BL808 CPU

OpenBouffalo provide a 'really work' Linux OS (not just a kernel) for BL808 CPU (M1S and Ox64), with more drivers developed and integrated, please refer to BL808 Linux Driver Status for more info.

If you want to try Linux with BL808, you should use this image instead of bl808_linux prototype since Bouffalo Lab have said they will not maintain their initial Linux release at the moment, It is understandable that Linux supporting is not the first goal of BL Lab.

Build OpenBouffalo Linux Image

The building process is simple :

mkdir buildroot_bouffalo && cd buildroot_bouffalo
git clone https://github.com/buildroot/buildroot
git clone https://github.com/openbouffalo/buildroot_bouffalo
export BR_BOUFFALO_OVERLAY_PATH=$(pwd)/buildroot_bouffalo
cd buildroot
make BR2_EXTERNAL=$BR_BOUFFALO_OVERLAY_PATH pine64_ox64_defconfig
make

It will download toolchains / source packages from internet, may take one or more hours to build, be patient until it built.

You can stop the building process at any time by 'Ctrl-C', it will continue building when re-run 'make'.

After built successfully, bl808 firmwares and sdcard image will be generated in output/images dir. Note the m0 / d0 lowload firmwares is built with ".fw_header" (new firmware format).

If you don't like to build it yourself, you can download the prebuilt image directly from https://github.com/openbouffalo/buildroot_bouffalo/releases/. There are two images currently : a minimal image 'bl808-linux-pine64_ox64_defconfig.tar.gz' and a more complete image : bl808-linux-pine64_ox64_full_defconfig.tar.gz.

Inside the archive you will find the following files:

I also put a copy of v1.0.1 at openboufalo-linux-firmware dir in this repo, and write a script to combine all firmwares, since I want to programm them from command line and have to combine all firmwares together to get rid of using BLDevCube.

Program with bflb-iot-tool and flash a SD Card

If you want to program by 'bflb-iot-tool' from commandline, After you download V1.0.1 openbouffalo image, you need combined m0/d0 lowload and bl808-firmware.bin together as:

# create a empty image of size 0x800000 and fill it with "0xFF".
# 0x800000 is the start addr of "bl808-firmware.bin".
dd if=/dev/zero bs=8388608 count=1| tr "\000" "\377" >openbouffalo-bl808.bin

# copy "m0_lowload_bl808_m0.bin" to the start of openbouffalo-bl808.bin
dd conv=notrunc if=m0_lowload_bl808_m0.bin of=openbouffalo-bl808.bin

# copy "d0_lowload_bl808_d0.bin" to 0x100000
dd conv=notrunc if=d0_lowload_bl808_d0.bin of=openbouffalo-bl808.bin seek=1048576 bs=1

# append "bl808-firmware.bin" to the end
cat bl808-firmware.bin >> openbouffalo-bl808.bin

A script create-full-image.sh can be used directly to create the final "openbouffalo-bl808.bin" image.

Then activate UART programming mode and program it as:

bflb-iot-tool --chipname bl808 --interface uart --port /dev/ttyUSB1 --baudrate 2000000 --firmware openbouffalo-bl808.bin --addr 0x0 --single

After BL808 programmed, you need prepare a microSD card and flash sdcard img to it, before run below dd command, please make sure which device is the microSD card, and replace '/dev/sdX' as your microSD card device.

xz -d sdcard-pine64_ox64_[full_]defconfig.img.xz
sudo dd if=sdcard-pine64_ox64_[full_]defconfig.img of=/dev/sdX bs=1M

Program with BLDevCube and flash a SD Card

After image tarball downloaded and extracted:

Run OpenBouffalo Linux

Open a terminal and run tio as:

tio -b 20000 /dev/ttyUSB0

Change the serial device according to your env.

Then press the 'RESET' button on board, the booting progress look like :

[I][]
[I][]   ____                   ____               __  __      _
[I][]  / __ \                 |  _ \             / _|/ _|    | |
[I][] | |  | |_ __   ___ _ __ | |_) | ___  _   _| |_| |_ __ _| | ___
[I][] | |  | | '_ \ / _ \ '_ \|  _ < / _ \| | | |  _|  _/ _` | |/ _ \
[I][] | |__| | |_) |  __/ | | | |_) | (_) | |_| | | | || (_| | | (_) |
[I][]  \____/| .__/ \___|_| |_|____/ \___/ \__,_|_| |_| \__,_|_|\___/
[I][]        | |
[I][]        |_|
[I][]
[I][] Powered by BouffaloLab
[I][] Build:11:52:04,Mar  6 2023
[I][] Copyright (c) 2023 OpenBouffalo team
[I][] Copyright (c) 2022 Bouffalolab team
[I][] dynamic memory init success,heap s[I][LowLoad] D0 start...
[I][LowLoad] low_load start...
......
Select the boot mode
1:      Pine64 0X64 Kernel
2:      Sipeed M1SDock Kernel
Enter choice: 2:        Sipeed M1SDock Kernel
Retrieving file: /extlinux/../Image
append: root=PARTLABEL=rootfs rootwait rw rootfstype=ext4 console=ttyS0,2000000 loglevel=8 earlycon=sbi
Retrieving file: /extlinux/../bl808-sipeed-m1s.dtb
## Flattened Device Tree blob at 51ff8000
   Booting using the fdt blob at 0x51ff8000
Working FDT set to 51ff8000
   Loading Device Tree to 0000000053f21000, end 0000000053f25009 ... OK
Working FDT set to 53f21000

Starting kernel ...

[    0.000000] Linux version 6.2.0 (runner@fv-az351-898) (riscv64-unknown-linux-gnu-gcc (Xuantie-900 linux-5.10.4 glibc gcc Toolchain V2.6.1 B-20220906) 10.2.0, GNU ld (GNU Binutils) 2.35) #1 Mon Mar  6 11:10:01 UTC 2023
......

Root Partition Already resized
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Starting mdev... OK
Initializing random number generator: OK
Saving random seed: OK
Starting iptables: OK
Starting network: OK
Starting dropbear sshd: OK

Welcome to Buildroot
ox64 login:

When login prompt, login as 'root'.

Miscellaneous

how to build and program uartjtag and dualuart firmware for Sipeed RV Debugger Plus

Upstream repo for Sipeed RV Debugger Plus is https://github.com/sipeed/RV-Debugger-BL702/, The build instruction in README.md is outdated.

We do not use the outdated version of bl_mcu_sdk shipped with Sipeed RV Debugger Plus in this tutorial, just build the 'uartjtag' and 'dualuart' firmwares with it.

git clone https://github.com/sipeed/RV-Debugger-BL702
git submodule update --init --progress
cd firmware/bl_mcu_sdk

To build jtaguart firmware for Sipeed RV Debugger Plus:

make BOARD=bl702_debugger APP_DIR=../app APP=usb2uartjtag

If all good, the target file is 'out/app/usb2uartjtag/usb2uartjtag_bl702.bin'.

To build dualuart firmware for Sipeed RV Debugger Plus:

make BOARD=bl702_debugger APP_DIR=../app APP=usb2dualuart

If all good, the target file is 'out/app/usb2dualuart/usb2dualuart_bl702.bin'.

To program these firmwares to Sipeed RV Debugger Plus, you can use:

bflb-mcu-tool --chipname=bl702 --interface=uart --port=/dev/ttyACM0 --baudrate=2000000  <firmware.bin>

Or

bflb-iot-tool --chipname=bl702 --port=/dev/ttyACM0 --baudrate=2000000 --addr 0x2000 --firmware=<firmware.bin>

Or

blisp iot -c bl70x --reset -s <firmware.bin> -l 0x2000

how to turn M0S Dock to CK-Link Lite

The CK-Link Lite firmware for M0S Dock is in m0s_dock_cklink-lite_firmware dir.

Hold the BOOT button down and power on M0S Dock by plug it in PC USB port, and program it as:

$ bflb-mcu-tool --chipname=bl616 --interface=uart --port=/dev/ttyACM0 --baudrate=2000000 --firmware=bl616-cklink-lite.bin

M0sense board (BL702) programming notes

Sipeed M0sense is an AIOT development board based on BL702 of Bouffalo Lab, it's RISC-V architecture, supports low-energy bluetooth. There is a 8Pins FPC connector for connecting LCD screen, and 1 microphone, 1 RGB LED and a six-axis sensor chip are on this board. One USB 2.0 FS routes to Type-C interface.

It has 'BOOT' and 'RESET' buttons indeed, but NOT for entering UART programming mode, it's for entering U-Disk programming mode with factory firmware.

To enter UART programming mode I metioned above many times, you need to short the 3v3 and boot pin, then power it, the M0sense board will enter UART programming mode.

After that, you can program it with bflb-mcu-tool etc.

how to restore factory firmwares for M1S Dock

All factory firmwares for M1S Dock is in m1s_dock_factory_firmware dir.

The files in this dir includes:

01-restore-bl702-dualuart-firmware.sh and 02-restore-bl808-factory-firmware.sh can be used to restore the factory formware for Sipeed M1S Dock from command line.

03-program-d0-firmware.sh can be used to program all other D0 factory demos or firmware you build from SDK for Sipeed M1S Dock from command line.

To restore or fix dualuart firmware for BL702:

./01-restore-bl702-dualuart-firmware.sh

To restore factory firmwares for BL808:

./02-restore-bl808-factory-firmware.sh

To program other firmwares for D0 of BL808 (no matter factory demos or firmwares built from M1S SDK):

./03-program-d0-firmware.sh <firmware>

Deprecated

bl_iot_sdk

bl_iot_sdk was deprecated

Bouffalolab bl_iot_sdk support BL602 Wi-Fi/BLE Combo RISC-V based Chip and BL70X Zigbee/BLE RISC-V based Chip.

The full bl_iot_sdk will occupies 9G disk space since it contains all prebuilt toolchains for Windows / MacOSX (ARM and X86) and Linux (ARM and X86). If the bandwidth and disk space is not a issue for you, you can git clone https://github.com/bouffalolab/bl_iot_sdk directly, since toolchains for all supported platform included in it, it will be easy to use.

I recommend use bl_iot_sdk_tiny.

git clone https://github.com/bouffalolab/bl_iot_sdk_tiny
cd bl_iot_sdk_tiny
git submodule update --init --recursive --progress
cd components && git checkout
cd tools && git checkout
cd docs && git checkout
cd customer_app && git checkout

bl_iot_sdk only works with SiFive GCC Toolchain. you can either use the full 'bl_iot_sdk' repo, it contains pre-built Windows / MacOSX / Linux toolchains and occupies about 14G disk space. or use 'bl_iot_sdk_tiny and setup toolchain as :

cd bl_iot_sdk_tiny
sudo bash ./scripts/setup.sh

It will download the SiFive gcc toolchain from bouffalo lab's official website and setup it automatically.

After toolchain installed, let's build the blink demo for BL602 to blink a LED connect to GPIO 5:

cd customer_app/get-start/blink
./genromap

If all good, build_out/blink.bin will be generated.

Then program it to XT-BL12 devboard by :

bflb-iot-tool --chipname=bl602 --port=/dev/ttyUSB0 --baudrate=2000000 --firmware=build_out/blink.bin

Don't forget enter programming mode first by Hold the 'D8' (GPIO8) button down, press and release 'EN' button, then release 'D8' (GPIO8) button.

After programming finished, you may need reset the device to blink the LED connect to GPIO 5.

Build linux kernel for BL808

This section is deprecated since Bouffalo Lab have said they will not maintain their initial Linux release at the moment.

The linux kernel building for C906 core of BL808 is worth a seperate section.

When we setup toolchain, I alreay mentioned the XuanTie RISC-V linux toolchain, and it never used in above sections. The RISC-V linux toolchain is only useful for building a linux kernel for C906 core of BL808.

Although there are still some drivers missing, but linux kernel can boot and run with BL808 already.

Before building the linux kernel, make sure you setup toolchains correctly.

Build linux kernel

Upstream git is https://github.com/bouffalolab/bl808_linux, but the 'build.sh' need some changes to work better, you can use my fork now.

git clone https://github.com/cjacker/bl808_linux.git
git checkout for_tutorial

If you use Sipeed M1S Dock, please run :

./switch_to_m1sdock.sh

It will apply a patch to setup UART pins for M1S Dock.

Then build it step by step:

./build.sh opensbi
./build.sh kernel_config
./build.sh kernel
./build.sh dtb
./build.sh low_load
./build.sh whole_bin

Or

./build.sh all

When ./build.sh kernel_config, it will launch kernel menuconfig, just exit directly or change kernel configuration if you really understand what you changed.

If all good, the result firmwares will be generated at 'out' dir:

I put all pre-built firmwares at 'm1s_linux_firmware' dir in this repo.

Program linux kernel

with bflb-mcu-tool

At first, I didn't find a way to program two "low_load" firmwares from command line, bflb-mcu-tool always erase and re-write bootinfo when programming second firmware. I keep 2 correct log files 'log.mcu' and 'log.iot' in m1s_linux_firmware dir, these log files is copied from BLDevCube.

From the log:

The root cause we can not use bflb-mcu-tool to program these 2 low_load firmwares is it did not export group1 related args.

After reading the codes of bflb-mcu-tool, I found it's very easy to enable group1 support with a few code changes.

The patch 'bflb_mcu_tool-1.8.3-enable-group1.patch' is for bflb_mcu_tool v1.8.3 (latest version when writing this tutorial), since bflb_mcu_tool can be installed by pip, you should install it as:

pip install 'bflb-mcu-tool==1.8.3' --force-reinstall

Then patch it as:

cd $HOME/.local/lib/python?.?/site-packages/bflb_mcu_tool/core/
cat <path>/bflb_mcu_tool-1.8.3-enable-group1.patch |patch -p0

After patched, bflb-mcu-tool will support 2 new args: --group1-firmware GROUP1_FIRMWARE --group1-addr GROUP1_ADDR

Program 2 low_load firmwares as:

bflb-mcu-tool --chipname bl808 --interface uart --port /dev/ttyUSB1 --baudrate 2000000 --firmware low_load_bl808_m0@0x58000000.bin --addr 0x58000000 --group1-firmware low_load_bl808_d0@0x58000000.bin --group1-addr 0x58000000

For whole_img_linux@0xD2000.bin, it can be programmed from command line by:

bflb-iot-tool --chipname bl808 --interface uart --port /dev/ttyUSB1 --baudrate 2000000 --firmware whole_img_linux@0xD2000.bin --addr 0xD2000 --single

Or

bflb-mcu-tool --chipname bl808 --interface uart --port /dev/ttyUSB1 --baudrate 2000000 --firmware whole_img_linux@0xD2000.bin --addr 0xD0000

Note --addr 0xD0000 for bflb-mcu-tool and --addr 0xD2000 --single for bflb-iot-tool.

When using bflb-mcu-tool to program the 'whole_img_linux@0xD2000.bin', 'bootinfo_group0.bin' will generated again and program to 0x0000, it will erase and replace the 'bootinfo_group0' for 'low_load_bl808_m0@0x58000000.bin', you need program 2 low_load firmwares again:

bflb-mcu-tool --chipname bl808 --interface uart --port /dev/ttyUSB1 --baudrate 2000000 --firmware low_load_bl808_m0@0x58000000.bin --addr 0x58000000 --group1-firmware low_load_bl808_d0@0x58000000.bin --group1-addr 0x58000000

with BLDevCube

  1. Connect M1S Dock 'UART' typec port with PC by USB cable
  2. Set BL808 board to programming mode:
    • Press BOOT button
    • Press RESET button
    • Release RESET button
    • Release BOOT button
  3. Run DevCube, select [BL808], and switch to [MCU] page
  4. Select the uart port and set baudrate with 2000000
  5. M0 Group[Group0] Image Addr [0x58000000] [PATH to low_load_bl808_m0.bin]
  6. D0 Group[Group1] Image Addr [0x58000000] [PATH to low_load_bl808_d0.bin]
  7. Click 'Create & Download' and wait until it's done
  1. Switch to [IOT] page
  2. Enable 'Single Download', set Address with 0xD2000, choose [PATH to whole_image_linux.bin]
  3. Click 'Create & Download' again and wait until it's done.

You may wonder why the ADDR of M0 / D0 low_load firmwares is same, they all are 0x58000000. To understand memory layout and bootrom better, please refer to : https://btashton.github.io/bl808-notes/

Boot Linux kernel

  1. Use any serial terminal such as tio, set baudrate to 2000000, and open "/dev/ttyUSB0".

    tio -b 2000000 /dev/ttyUSB0
  2. Reset M1S Dock by pressing RST button, you will receive boot msgs.

  3. Login as root.

dynamic memory init success,heap size = 26 Kbyte
C906 start...
mtimer clk:1000000
linux load start...
len:0x00376c53
vm linux load done!
dtb load done!
opensbi load done!

load time: 426313 us

OpenSBI v0.6
   ____                    _____ ____ _____
  / __ \                  / ____|  _ \_   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  \____/| .__/ \___|_| |_|_____/|____/_____|
        | |
        |_|

Platform Name          : T-HEAD Xuantie c910
Platform HART Features : RV64ACDFIMSUVX
Platform Max HARTs     : 1
Current Hart           : 0
Firmware Base          : 0x3eff0000
Firmware Size          : 56 KB
Runtime SBI Version    : 0.2

--------Start Local Services--------
********************************

Linux login: root
login[40]: root login on 'ttyS0'
Processing /etc/profile ...
Set search library path in /etc/profile
Set user path in /etc/profile
id: unknown ID 0
Welcome to Linux
[@Linux root]#