发帖
8 0 0

树莓派/Orange Pi 也能编译 Ai-Thinker-WB2 —— ARM 架构完整踩坑指南

业余菜狗
论坛元老

30

主题

171

回帖

5002

积分

论坛元老

积分
5002
Ai-WB2系列 102 8 3 天前
[i=s] 本帖最后由 业余菜狗 于 2026-8-4 08:59 编辑 [/i]

树莓派/Orange Pi 也能编译 Ai-Thinker-WB2 —— ARM 架构完整踩坑指南

适用环境:ARM 架构开发板(树莓派、Orange Pi 等)上编译 Ai-Thinker-WB2 SDK
系统:Ubuntu 22.04(aarch64 / ARM 64 位)
SDK:Ai-Thinker-WB2
关键词:ARM 交叉编译 / RISC-V 工具链 / BL602 / Ai-WB2

📌 引言

在用树莓派、Orange Pi 这类 ARM 架构开发板编译安信可 Ai-WB2 的 SDK 时,直接照官方 README 执行 make,结果一编译就报各种错误:

text

fatal error: string.h: No such file or directory

或者:

text

ABI is incompatible with that of the selected emulation

以为是自己环境装错了,其实是 SDK 自带的编译工具链是 x86 架构的,在 ARM 上根本跑不起来。

本贴把我实际踩坑、并最终编译成功的过程完整记录下来,希望能帮到同样在 ARM 平台上折腾的朋友。

🔍 问题根源:工具链是 x86 的

Ai-Thinker-WB2 SDK 克隆下来后,自带一套 RISC-V 交叉编译工具链,位于:

text

toolchain/riscv/Linux/bin/

file 命令看一下就明白了:

bash

file toolchain/riscv/Linux/bin/riscv64-unknown-elf-gcc

输出:

text

ELF 64-bit LSB executable, x86-64, ... for GNU/Linux

架构是 x86-64,你的树莓派/Orange Pi 是 aarch64CPU 指令集都不一样,直接跑不了,所以编译必挂。

💡 总体思路:三件事

既然自带的工具链不能用,思路就是「换一套 ARM 能跑的工具链」,共三步:

步骤 内容 说明
1 安装 Ubuntu 官方的原生 RISC-V 工具链 版本正好也是 10.2.0,和 SDK 要求的一致
2 补齐 newlib Ubuntu 的 gcc 包不自带 C 库头文件,要从 SDK 自带的工具链里复制过来
3 补齐 multilib 映射 SDK 用 rv32imc 编译,但 Ubuntu 工具链的目录结构里没有它,要手动补上

下面一步步来。

📦 第一步:克隆项目(含子模块)

工具链是以子模块方式存放的,一定要用 --recursive 克隆,否则 toolchain/ 目录是空的:

bash

git clone --recursive https://gitee.com/Ai-Thinker-Open/Ai-Thinker-WB2.git

国内用户推荐 Gitee 源,速度快。克隆完成后确认工具链目录存在:

bash

ls Ai-Thinker-WB2/toolchain/riscv/Linux/riscv64-unknown-elf/

能看到 includelib 两个目录就对了(后面要用的 newlib 就在这里)。

🔧 第二步:安装原生 RISC-V 工具链

Ubuntu 22.04 官方源里有现成的交叉编译工具链,直接装:

bash

sudo apt install -y gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf

验证版本:

bash

riscv64-unknown-elf-gcc --version

输出:

text

riscv64-unknown-elf-gcc () 10.2.0

版本正好是 10.2.0,和 SDK 自带的一致,兼容性最好。

📁 第三步:补齐 newlib 头文件和库

Ubuntu 的 gcc-riscv64-unknown-elf 是个裸机编译器,不带 C 库头文件和库文件string.hstdio.hlibc.a 这些都没有)。所以编译时才会报:

text

fatal error: string.h: No such file or directory

解决办法:SDK 自带的工具链里有完整的 newlib,而且这些头文件/库是给 RISC-V 目标用的,和宿主机架构无关,直接复制过来用:

bash

# 路径换成你的 SDK 实际位置
BUNDLED=/path/to/Ai-Thinker-WB2/toolchain/riscv/Linux/riscv64-unknown-elf

sudo mkdir -p /usr/riscv64-unknown-elf
sudo cp -a $BUNDLED/include/. /usr/riscv64-unknown-elf/include/
sudo cp -a $BUNDLED/lib/.     /usr/riscv64-unknown-elf/lib/

验证复制成功:

bash

ls /usr/riscv64-unknown-elf/include/string.h
ls /usr/riscv64-unknown-elf/lib/libc.a

两个文件都在就 OK。

🧩 第四步:补齐 multilib 映射(最坑的一步)

复制完 newlib 后再编译,会报新的错误:

text

/usr/riscv64-unknown-elf/lib/libc.a(lib_a-memcpy.o): ABI is incompatible with that of the selected emulation:
  target emulation `elf64-littleriscv' does not match `elf32-littleriscv'

翻译一下:链接器找不到 32 位(RV32)的 libc,回退用了顶层 64 位(RV64)的 libc,导致 ABI 不兼容。

原因分析

  • SDK 编译时用的是 -march=rv32imc -mabi=ilp32(见 make_scripts_riscv/project.mk
  • 但 Ubuntu 工具链的 multilib 列表里没有 rv32imc 这个目录,它会把 rv32imc 映射到 rv32im/ilp32
  • rv32im/ilp32 这个目录我们没建,所以链接器跑到顶层用了 RV64 的库

解决办法:用 SDK 自带工具链里对应 ABI 的库,把缺的两个映射目录补上。rv32imcrv32im 只差一个 C(压缩指令)扩展,ABI 完全兼容,可以混用:

bash

B=/path/to/Ai-Thinker-WB2/toolchain/riscv/Linux/riscv64-unknown-elf/lib

# rv32imc -> rv32im
sudo mkdir -p /usr/riscv64-unknown-elf/lib/rv32im/ilp32
sudo cp -a $B/rv32imc/ilp32/.  /usr/riscv64-unknown-elf/lib/rv32im/ilp32/

# rv32imfc -> rv32imf(有的项目用浮点 ABI,一并补上)
sudo mkdir -p /usr/riscv64-unknown-elf/lib/rv32imf/ilp32f
sudo cp -a $B/rv32imfc/ilp32f/. /usr/riscv64-unknown-elf/lib/rv32imf/ilp32f/

⚙️ 第五步:修改 toolchain.mk(免参数编译)

每次编译都要手动传一堆参数太麻烦,直接改配置文件一劳永逸。

编辑 make_scripts_riscv/toolchain.mk,把:

make

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

改成:

make

CONFIG_TOOLPREFIX ?= riscv64-unknown-elf-
CPATH ?= /usr/riscv64-unknown-elf/include
export CPATH

两个配置的作用:

配置 作用
CONFIG_TOOLPREFIX 改用系统 PATH 里的原生工具链
CPATH 告诉 gcc 去 /usr/riscv64-unknown-elf/include 找 newlib 头文件,export 保证子目录的 make 也能继承

✅ 第六步:编译并验证

配置完成后,编译就和其他平台一样简单了:

bash

cd applications/get-started/helloworld
make -j4

编译成功会看到:

text

Building Finish.

产物在 build_out/ 目录下:

text

build_out/helloworld.bin   # 可烧录的固件
build_out/helloworld.elf   # 调试用
build_out/helloworld.map   # 链接映射表

最后验证一下固件确实是 RISC-V 的:

bash

file build_out/helloworld.elf

输出:

text

ELF 32-bit LSB executable, UCB RISC-V, RVC, single-float ABI, version 1 (SYSV), statically linked

看到 32-bit LSB executable, UCB RISC-V 就说明编译完全正确,可以烧录了。

📋 常见报错对照表

报错 原因 解决办法
fatal error: string.h: No such file or directory newlib 头文件缺失 完成第三步,确认 CPATH 已设置
ABI is incompatible ... elf64-littleriscv does not match elf32-littleriscv multilib 映射缺失,链接到了 RV64 的 libc 完成第四步
bad value ... for -march 工具链版本过旧 确认安装的是 10.2.0 版本
riscv64-unknown-elf-gcc: command not found 工具链没装上 确认第二步 apt 安装成功

🚀 懒人专用:一键配置脚本

如果不想手动折腾,我把以上所有步骤封装成了一个脚本:setup_arm_toolchain.sh

bash

# 默认找当前目录下的 Ai-Thinker-WB2
bash setup_arm_toolchain.sh

# 或指定 SDK 路径
bash setup_arm_toolchain.sh /path/to/Ai-Thinker-WB2

脚本会自动完成:

  • ✅ 检测架构
  • ✅ 安装工具链
  • ✅ 复制 newlib
  • ✅ 补齐 multilib
  • ✅ 修改 toolchain.mk(重复运行也不会改坏,幂等)

需要 sudo 权限,会提示输入密码。

脚本内容如下(保存为 setup_arm_toolchain.sh):

bash

#!/bin/bash
# ARM 平台一键配置 Ai-Thinker-WB2 工具链

set -e

SDK_PATH="${1:-$(pwd)/Ai-Thinker-WB2}"

if [ ! -d "$SDK_PATH/toolchain/riscv/Linux/riscv64-unknown-elf" ]; then
    echo "错误: 找不到 SDK 工具链目录,请确认路径是否正确"
    echo "当前查找路径: $SDK_PATH/toolchain/riscv/Linux/riscv64-unknown-elf"
    exit 1
fi

echo "检测到 SDK 路径: $SDK_PATH"

# 第二步:安装工具链
echo ">>> 安装 RISC-V 工具链..."
sudo apt update
sudo apt install -y gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf

# 第三步:复制 newlib
echo ">>> 复制 newlib 头文件和库..."
BUNDLED="$SDK_PATH/toolchain/riscv/Linux/riscv64-unknown-elf"
sudo mkdir -p /usr/riscv64-unknown-elf
sudo cp -a $BUNDLED/include/. /usr/riscv64-unknown-elf/include/
sudo cp -a $BUNDLED/lib/.     /usr/riscv64-unknown-elf/lib/

# 第四步:补齐 multilib
echo ">>> 补齐 multilib 映射..."
B="$BUNDLED/lib"
sudo mkdir -p /usr/riscv64-unknown-elf/lib/rv32im/ilp32
sudo cp -a $B/rv32imc/ilp32/.  /usr/riscv64-unknown-elf/lib/rv32im/ilp32/
sudo mkdir -p /usr/riscv64-unknown-elf/lib/rv32imf/ilp32f
sudo cp -a $B/rv32imfc/ilp32f/. /usr/riscv64-unknown-elf/lib/rv32imf/ilp32f/

# 第五步:修改 toolchain.mk
echo ">>> 修改 toolchain.mk..."
TOOLCHAIN_MK="$SDK_PATH/make_scripts_riscv/toolchain.mk"
if [ -f "$TOOLCHAIN_MK" ]; then
    sed -i 's|CONFIG_TOOLPREFIX ?= $(BL60X_SDK_PATH)/toolchain/riscv/$(shell uname |cut -d '\''_'\'' -f1)/bin/riscv64-unknown-elf-|CONFIG_TOOLPREFIX ?= riscv64-unknown-elf-|g' "$TOOLCHAIN_MK"
    if ! grep -q "^CPATH ?=" "$TOOLCHAIN_MK"; then
        echo "CPATH ?= /usr/riscv64-unknown-elf/include" >> "$TOOLCHAIN_MK"
        echo "export CPATH" >> "$TOOLCHAIN_MK"
    fi
    echo "toolchain.mk 已更新"
else
    echo "警告: 找不到 toolchain.mk,请手动修改"
fi

echo ""
echo "=========================================="
echo "✅ 配置完成!现在可以正常编译了"
echo "测试命令: cd applications/get-started/helloworld && make -j4"
echo "=========================================="

📝 结语

总结一下 ARM 平台编译 Ai-WB2 的完整链路:

text

装原生工具链(10.2.0) -> 复制 newlib 到 /usr/riscv64-unknown-elf/
-> 补 rv32im / rv32imf 两个 multilib 目录
-> 改 toolchain.mk 指向系统工具链
-> make -j4 收工

核心就一句话:SDK 自带的工具链是 x86 的,换成 Ubuntu 原生的 RISC-V 工具链,再补上 newlib 和 multilib 目录就行了。

如果过程中遇到问题,欢迎在楼下留言交流,我会尽量帮忙排查。

upload 附件:setup_arm_toolchain.zip

──── 0人觉得很赞 ────

使用道具 举报

[i=s] 本帖最后由 业余菜狗 于 2026-8-4 10:05 编辑 [/i]

树莓派/Orange Pi 也能烧录 Ai-WB2 —— make flash ARM 适配踩坑记录(2楼补充)

接上一帖:上篇讲了在 ARM 开发板上编译 Ai-Thinker-WB2 固件,这篇接着讲 烧录(make flash) 的坑。

适用环境:ARM 架构开发板(树莓派、Orange Pi 等)上烧录 Ai-Thinker-WB2 固件
系统:Ubuntu 22.04(aarch64 / ARM 64 位)
SDK:Ai-Thinker-WB2

🔍 问题根源:烧录工具也是 x86 的

在 ARM 板子上编译都通过了,结果 make flash 又翻车——报各种错误根本烧不进去。

原因和上一帖如出一辙:SDK 自带的烧录工具也是 x86 的,ARM 上跑不了。

make flash 默认调用 tools/flash_tool/bflb_iot_tool-ubuntu(见 make_scripts_riscv/project.mk)。它同样是 x86-64 预编译二进制:

bash

file tools/flash_tool/bflb_iot_tool-ubuntu

输出:

text

ELF 64-bit LSB executable, x86-64 ...

所以在 aarch64 上直接执行就报:

text

cannot execute binary file: Exec format error

解决方案:官方发布了纯 Python 版烧录工具 bflb-iot-tool(PyPI 上可以直接装),跨平台、ARM 上原生运行,功能和二进制版本完全一致。我们只需做一个同名包装脚本把参数转发给它,make flash 就能照常用。

📦 详细步骤

第一步:安装 Python 版烧录工具

bash

pip3 install --user bflb-iot-tool

验证:

bash

bflb-iot-tool --help

如果提示 command not found,确认 ~/.local/bin 是否在 PATH 中:

bash

export PATH=$PATH:~/.local/bin
# 或永久添加到 ~/.bashrc
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc

第二步:备份原版 x86 二进制

SDK 里有两份该二进制,都要处理:

bash

FT=/path/to/Ai-Thinker-WB2/tools/flash_tool

mv $FT/bflb_iot_tool-ubuntu               $FT/bflb_iot_tool-ubuntu.x86
mv $FT/blflash_tools/bflb_iot_tool-ubuntu $FT/blflash_tools/bflb_iot_tool-ubuntu.x86

第三步:创建同名包装脚本

在两个位置各建一个文件 bflb_iot_tool-ubuntu,内容相同:

bash

#!/usr/bin/env bash
exec bflb-iot-tool "$@"

加执行权限:

bash

chmod +x $FT/bflb_iot_tool-ubuntu $FT/blflash_tools/bflb_iot_tool-ubuntu

原理:makefile 调用 ./bflb_iot_tool-ubuntu 时,实际执行的是包装脚本,把参数转手交给 ARM 可用的 Python 工具。makefile 一行都不用改。

🔥 实际烧录

bash

make flash SERIAL_PORT=/dev/ttyUSB0 SERIAL_BAUDRATE=921600

⚠️ 重要:这个版本的 makefile 里 SERIAL_PORT / SERIAL_BAUDRATE 没有默认值,必须手动传(网上很多旧教程写的 make flash p=/dev/ttyUSB0 b=921600 是旧版写法,本版本不生效)。

进入下载模式(关键!)

烧录前必须让芯片进入 UART 下载模式,否则会握手失败:

步骤 操作
1 BOOT 脚(GPIO8)拉高:按住板上的 BOOT 键
2 复位:按住 BOOT 的同时按一下 EN/RESET 键
3 松键顺序:先松 EN/RESET,再松 BOOT
4 接线:板子 RX ↔ 转串口 TXTX ↔ 转串口 RX共地

确认串口设备:

bash

ls /dev/ttyUSB* /dev/ttyACM*      # CH340/CP2102 一般是 /dev/ttyUSB0

当前用户需要在 dialout 组才能访问串口:

bash

groups                               # 确认包含 dialout
sudo usermod -aG dialout $USER       # 没有就添加,需重新登录生效

成功烧录会看到进度条和成功提示。

📋 常见报错排查

报错 原因 解决
Exec format error 还在用 x86 的 bflb_iot_tool-ubuntu 确认已替换为包装脚本
bflb-iot-tool: command not found Python 工具没装 / 不在 PATH 重新 pip3 install --user,确认 ~/.local/bin 在 PATH
handshake failed / ack is not ok 板子不在下载模式 / 接线错 / 供电不足 重新走「进入下载模式」,检查 RX/TX 和 GPIO8 拉高
Permission denied 用户不在 dialout 组 sudo usermod -aG dialout $USER 后重新登录
No such file or directory 串口设备名不对 ls /dev/ttyUSB* 确认实际设备名

🚀 懒人专用:一键配置脚本

手动步骤麻烦,我封装成了 setup_arm_flash.sh

bash

# 默认找当前目录下的 Ai-Thinker-WB2
bash setup_arm_flash.sh

# 或指定 SDK 路径
bash setup_arm_flash.sh /path/to/Ai-Thinker-WB2

脚本自动完成:检测架构 → 装 Python 烧录工具 → 备份 x86 二进制 → 生成包装脚本 → 检查串口权限。重复运行也不会改坏(已配置会跳过),可放心使用。

脚本内容如下(保存为 setup_arm_flash.sh):

bash

#!/bin/bash
# ARM 平台一键配置 Ai-Thinker-WB2 烧录工具

set -e

SDK_PATH="${1:-$(pwd)/Ai-Thinker-WB2}"

if [ ! -d "$SDK_PATH/tools/flash_tool" ]; then
    echo "错误: 找不到 SDK 烧录工具目录,请确认路径是否正确"
    echo "当前查找路径: $SDK_PATH/tools/flash_tool"
    exit 1
fi

echo "检测到 SDK 路径: $SDK_PATH"

# 检查架构
ARCH=$(uname -m)
if [[ "$ARCH" != "aarch64" && "$ARCH" != "arm64" && "$ARCH" != "armv7l" ]]; then
    echo "警告: 当前架构为 $ARCH,本脚本主要针对 ARM 平台设计"
    read -p "是否继续?(y/N) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

# 第一步:安装 Python 工具
echo ">>> 安装 bflb-iot-tool..."
if ! command -v bflb-iot-tool &> /dev/null; then
    pip3 install --user bflb-iot-tool
    export PATH=$PATH:~/.local/bin
    echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
else
    echo "bflb-iot-tool 已安装,跳过"
fi

# 第二步:备份 x86 二进制
echo ">>> 备份原版 x86 二进制..."
FT="$SDK_PATH/tools/flash_tool"
if [ -f "$FT/bflb_iot_tool-ubuntu" ] && [ ! -f "$FT/bflb_iot_tool-ubuntu.x86" ]; then
    mv "$FT/bflb_iot_tool-ubuntu" "$FT/bflb_iot_tool-ubuntu.x86"
    echo "已备份: $FT/bflb_iot_tool-ubuntu.x86"
fi
if [ -f "$FT/blflash_tools/bflb_iot_tool-ubuntu" ] && [ ! -f "$FT/blflash_tools/bflb_iot_tool-ubuntu.x86" ]; then
    mv "$FT/blflash_tools/bflb_iot_tool-ubuntu" "$FT/blflash_tools/bflb_iot_tool-ubuntu.x86"
    echo "已备份: $FT/blflash_tools/bflb_iot_tool-ubuntu.x86"
fi

# 第三步:创建包装脚本
echo ">>> 创建包装脚本..."
create_wrapper() {
    local target="$1"
    cat > "$target" << 'EOF'
#!/usr/bin/env bash
exec bflb-iot-tool "$@"
EOF
    chmod +x "$target"
    echo "已创建: $target"
}

create_wrapper "$FT/bflb_iot_tool-ubuntu"
create_wrapper "$FT/blflash_tools/bflb_iot_tool-ubuntu"

# 第四步:检查串口权限
echo ">>> 检查串口权限..."
if groups | grep -q dialout; then
    echo "当前用户已在 dialout 组"
else
    echo "⚠️ 当前用户不在 dialout 组,添加后需重新登录生效:"
    echo "   sudo usermod -aG dialout $USER"
fi

echo ""
echo "=========================================="
echo "✅ 烧录工具配置完成!"
echo "烧录命令: make flash SERIAL_PORT=/dev/ttyUSB0 SERIAL_BAUDRATE=921600"
echo "=========================================="
echo ""
echo "⚠️ 烧录前记得让板子进入下载模式:"
echo "   1. 按住 BOOT 键"
echo "   2. 按一下 EN/RESET 键"
echo "   3. 先松 EN/RESET,再松 BOOT"

📝 结语

ARM 平台烧录 Ai-WB2 的链路整理:

text

装 Python 版 bflb-iot-tool
-> 把 x86 的 bflb_iot_tool-ubuntu 换成同名包装脚本
-> make flash SERIAL_PORT=/dev/ttyUSB0 SERIAL_BAUDRATE=921600
-> 板子进下载模式(BOOT+EN)
-> 收工 ✅

一句话总结:编译和烧录的工具都是 x86 的,编译换成系统 RISC-V 工具链,烧录换成纯 Python 版 bflb-iot-tool,ARM 上就全都能跑。

如果过程中遇到问题,欢迎在楼下留言交流,我会尽量帮忙排查。

upload 附件:setup_arm_flash.zip

狗哥厉害👍

AI搞得啦~

测试过没,编译耗时不
前天 11:32
bzhou830 发表于 2026-8-5 08:26
测试过没,编译耗时不

我用香橙派zero2w编译烧录过,速度一般,应急还是可以的
业余菜狗 发表于 2026-8-5 11:32
我用香橙派zero2w编译烧录过,速度一般,应急还是可以的

那手机上应该也可以编译
前天 18:08
bzhou830 发表于 2026-8-5 14:25
那手机上应该也可以编译

按理说可以的

狗哥厉害
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 31239 个
  • 话题数: 42370 篇