ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

星闪BS21E开发环境搭建:从工具链到串口日志的完整实践

星闪BS21E开发环境搭建:从工具链到串口日志的完整实践

星闪BS21E开发板的安装环境搭建,说小不小,说大不大。很多人拿到板子之后,第一道坎就卡在编译环境上:工具链装好了编译报错,SDK解压出来路径带中文,串口死活不出日志……这些我都踩过。这篇文章把我从零开始搭环境、编译第一个固件、烧录并看到串口日志的完整过程写出来,包括过程中踩过的坑和排查思路,适合刚入手BS21E、之前又没怎么碰过嵌入式Linux开发环境的朋友参考。

1. 环境搭建的整体思路与任务拆解

1.1 先说清楚BS21E是个什么东西

星闪(NearLink)是一种短距离无线通信技术,和蓝牙、Wi-Fi这类技术处在同一个赛道。它分为两种模式:SLE低功耗模式,面向键鼠、穿戴设备、遥控器这类对功耗敏感的场景;SLB高速模式,面向音频、投屏、数据分发这类高吞吐场景。BS21E就是一颗低功耗星闪SoC,带射频收发、基带处理、协议栈,外加UART、SPI、I2C、GPIO这些常用外设接口,所以在物联网终端、人机交互设备、无线传感器节点里都能见到它。

环境搭建这件事,本质上就四件事:准备好交叉编译工具链,下载并解压官方SDK,把示例工程编译成固件,再把固件烧到板子上并通过串口看到日志输出。听起来简单,但每一步之间都有耦合关系,工具链版本和SDK版本匹配不上、路径里有空格或中文、USB转串口驱动没装好,都会让整个过程卡住。这也是我写这篇东西的初衷——把这些坑提前标出来。

1.2 为什么选择Linux环境而不是Windows

BS21E官方SDK的编译脚本基本都是shell脚本加Makefile体系,在原生Linux环境下最省事。Windows下虽然也能通过做一套GNU环境来跑,但路径分隔符、行尾符、脚本解释器这些小问题会轮番折磨你,一旦报错,你甚至分不清是工具链问题还是系统兼容性问题。

我用的是虚拟机里的Ubuntu系统,分配了4核CPU和8GB内存,编译这种规模的嵌入式工程绰绰有余。如果你电脑配置紧张,2核4GB也能编译,只是全量编译时会慢一些。不建议用WSL1,文件IO性能差,烧录串口直连也麻烦;WSL2稍好,但USB设备透传还需额外配置。条件允许的话,直接用VirtualBox或VMware跑一个Ubuntu 20.04或22.04,这是我一直觉得最顺的路径。

提示:宿主Windows上装完虚拟机后,记得装虚拟机扩展包,这样USB串口设备才能透传到虚拟机里,否则后面烧录时根本找不到设备。

1.3 环境搭建的整体路径

先在心里画一条主线,后面所有操作都不会跑偏:

  1. 安装交叉编译工具链,确认gcc、make、python3基本工具可用;
  2. 下载SDK并解压到纯英文无空格路径;
  3. 查看SDK里的README或编译脚本,确认当前版本需要的工具链型号;
  4. 进入示例工程目录执行编译,生成hex/bin固件;
  5. 连接开发板USB串口,安装驱动并确认设备节点;
  6. 用厂家烧录工具下载固件;
  7. 打开串口终端,复位板子,观察启动日志。

这条主线看着简单,每一步都有需要留意的地方,下面分章节细说。

2. 工具链、SDK与硬件准备

2.1 开发板上的板载资源

BS21E开发板上通常有一颗主控芯片、一个USB转串口芯片、若干按键和LED,还要引出天线座。USB转串口芯片的作用是让电脑通过USB识别出一个虚拟串口,一方面用于烧录,另一方面用于打印日志。

拿到板子先看丝印,找到丝印标注UART_TX、UART_RX、BOOT、RST这几个关键位置。BOOT按键在烧录时有用,通常需要按住BOOT再按一下复位,让芯片进入ISP下载模式。很多新手不知道这个操作,结果烧录工具一直报“连接失败”,其实根本不是工具问题,是板子没进入下载模式。

串口参数一般是115200、8N1、无流控,但个别版本波特率可能是921600或者别的,具体以SDK文档为准。如果串口工具能看到乱码,大概率是波特率不对,而不是板子坏了。

2.2 交叉编译工具链的安装

BS21E属于ARM Cortex-M系列内核,所以需要arm-none-eabi-gcc这套工具链。注意,这里不要图新鲜去装最新版GCC,而是要尽量靠近SDK文档里推荐的那个版本。我这次SDK文档明确写着推荐使用某个特定版本范围的arm-none-eabi-gcc,我就老老实实按那个装了,编译一次通过;后来我在另一台机器上装了最新版,同一个工程却冒出一些奇怪的编译警告,虽然也能编过,但总觉得不放心。

安装步骤可以这样做:

# 下载工具链压缩包,放到 ~/tools 目录 mkdir -p ~/tools cd ~/tools # 解压 tar -xJf arm-none-eabi-gcc-xxx.tar.xz # 把工具链加入PATH export PATH=$HOME/tools/arm-none-eabi-gcc-xxx/bin:$PATH

为了让环境变量永久生效,可以把export那行追加到~/.bashrc末尾,然后执行source ~/.bashrc。验证是否安装成功:

arm-none-eabi-gcc --version

如果屏幕能打印出版本号,第一步就过了。另外还需要确认make和python3存在:

make --version python3 --version

有些精简版Ubuntu默认没装make,提前执行sudo apt install build-essential补上,省得后面突然报“make: command not found”被打断。

注意:64位Linux系统跑一些旧版32位工具链可能会缺32位运行库,报No such file or directory,这时候需要安装lib32ncurses5之类的兼容库。具体名字因发行版而异,报错后顺着提示安装即可。

2.3 SDK下载与目录结构

SDK是从芯片厂家那里获取的,一般通过官网注册下载,或者找技术支持要。下载后用sha256校验一下安装包完整性,这一步很容易被忽略,但解压到一半报“压缩包损坏”时,你会想起它的。

SDK解压后,典型的目录结构大致是这样:

sdk/ ├── applications/ # 示例工程入口 ├── drivers/ # 外设驱动代码 ├── system/ │ ├── kernel/ # 内核相关 │ └── startup/ # 启动文件与链接脚本 ├── protocols/ # 星闪协议栈 └── tools/ # 编译脚本、烧录工具辅助脚本

不同版本的SDK目录命名可能略有不同,但基本思路一致。第一次接触时不要急着到处翻代码,先看根目录的README和tools/下的编译脚本。README会告诉你支持的开发板型号、工具链版本、编译命令格式,这些信息比你自己猜省事得多。

3. 编译环境的实操搭建

3.1 配置编译参数

进入示例工程前,先弄清楚SDK的编译系统是怎么组织的。常见的做法是Makefile顶层定义芯片型号、开发板型号、应用名这几个关键变量,然后归集到同一个编译流程里。

我这次运行的编译命令大致是这样的:

make chip=bs21e board=bs21e_devkit app=sle_uart

如果SDK支持直接进到应用目录编译,也可以在applications/sle_uart/下直接make。关键是看README,不同厂家习惯不一样,不要凭经验硬猜。

编译之前,我建议先跑一次make clean或者删除上一次的build目录,再开始全量编译。这能避免旧的中间文件干扰,尤其是当你换过工具链版本之后再编译时,这一步能省掉很多莫名其妙的问题。

3.2 第一次编译与产物解读

执行编译后,终端会滚动大量编译信息。第一次直接跑全量编译,我用了大概三四十秒,日志里能清晰地看到每一个C文件被编译、链接的过程:

CC drivers/uart/uart.c CC drivers/gpio/gpio.c ... LD build/bs21e_sle_uart.elf OBJCOPY build/bs21e_sle_uart.hex OBJCOPY build/bs21e_sle_uart.bin

编译产物通常放在一个build目录下,最关键的就是这三个文件:

  • .elf:带调试信息的可执行文件,给调试器用的;
  • .hex:Intel HEX格式,烧录软件常用;
  • .bin:纯二进制镜像,某些烧录方式用这个。

看到OBJCOPY行,基本就能确认编译成功了。这时最好把build目录里的.map文件留着——它是链接脚本的最终映射结果,将来排查“为什么变量没生效”“为什么函数被优化没执行”这类问题时,查map文件是最直接的途径。

提示:如果编译输出最后没有报错,但也没有生成hex,多半是Makefile里OBJCOPY命令没执行到,或者编译参数里关闭了hex生成选项。先查Makefile里对应的目标是否被正确触发。

3.3 典型编译错误与排查思路

编译错误是新手劝退主力,我把这次和以往遇到的高频报错整理成一个速查表:

现象根本原因解决办法
arm-none-eabi-gcc: command not foundPATH未配置或配置无效检查~/.bashrc,重新source后验证--version
make: command not foundbuild-essential未安装执行apt install build-essential
No such file or directory(工具链报错)64位系统缺32位库安装lib32ncurses5相关兼容库
fatal error: xxx.h: No such file or directorySDK路径含中文/空格,或头文件路径配置错误把SDK移动到纯英文路径,检查Makefile里INCLUDE路径
undefined reference to ...链接脚本或启动文件不匹配确认芯片型号变量是否正确,不要混用不同芯片的启动文件
编译通过但hex缺失Makefile目标配置遗漏手动执行OBJCOPY或检查hex生成选项
全量编译后莫名报错旧的build缓存干扰执行make clean后重新编译

这里面最隐蔽的是“编译一会报错,过一会又好了”这类随机问题。如果SDK路径里有中文或者空格,某些make内部函数会解析出错,表现为随机报错。当时我为了省事,把SDK放在“D盘/我的文档/星闪开发/单片机项目”这种目录下,结果编译时动不动说找不到文件。把SDK移到~/workspace/bs21e_sdk后整个世界干净了。

4. 烧录过程与串口调试

4.1 USB转串口驱动与设备识别

编译出hex之后,连接开发板和电脑。Windows下USB转串口芯片通常需要装驱动,Linux下大多数已经集成。接上USB后,执行:

ls /dev/ttyUSB*

或

ls /dev/ttyACM*

能看到设备节点就说明系统识别了。如果没有,检查USB线是否支持数据传输——有些线只能充电,不能传数据,这是特别容易踩的坑。

频繁遇到“Permission denied”的话,说明当前用户没有串口权限。把自己加入dialout用户组就能解决:

sudo usermod -aG dialout $USER

然后注销重新登录,问题基本消失。

4.2 烧录的具体操作流程

烧录工具用的是厂家提供的下载软件,具体名字不重要,关键是流程。先把波特率、串口号、固件路径这几个参数填好,然后让板子进入下载模式。

进入下载模式最常用的方式是:先按住BOOT按键不放,再按一下复位键,然后松开。有些板子是跳线帽控制启动方式,操作前看一下板卡丝印或SDK文档。

烧录过程大致是:

  1. 选择串口号,一般为/dev/ttyUSB0;
  2. 选择编译生成的hex或bin文件;
  3. 确认烧录起始地址和SDK文档一致;
  4. 点击下载;
  5. 日志区域出现“下载完成”或“校验成功”提示。

这里要提醒一句:烧录时芯片处于下载模式,程序并不会运行;烧完需要按一下复位键,让芯片从用户Flash启动,才会看到你编译的程序跑起来。

4.3 串口日志验证与波特率选择

烧录完成后,打开串口终端连接同一个串口,波特率先按115200试。串口工具我用的是minicom,平时偶尔也用PuTTY。minicom用法很简单:

minicom -D /dev/ttyUSB0 -b 115200

按一下板子的复位键,如果终端里滚动出一行行启动日志,整个环境就算闭环了。还有一个小细节:如果日志被截断或者上一次的残留数据干扰阅读,先点断开再重新连接,或者给板子断电重上电。

串口无输出时,优先级最高的检查顺序是:串口号对不对、TX/RX有没有接反、波特率对不对、有没有复位、板子电源有没有亮。大多数“板子坏了”的结论,最后都只是接线或者参数问题。

现象优先排查点
串口无任何输出板子是否复位;串口是否选对;TX/RX是否接反
输出乱码波特率不匹配;检查是否选了错误的串口
输出到一半卡死电源供电不足;SDK日志缓冲区溢出;外设异常导致死机
烧录成功后仍跑旧程序复位键没按;启动引脚配置不对;固件没烧到正确地址

5. 常见问题速查与独家实操心得

5.1 新手最容易踩的五个坑

第一个坑是工具链版本乱换。SDK在某个版本下验证过,换新工具链常常冒出莫名警告,甚至编译不过。嵌入式不是追新的地方,稳定压倒一切。

第二个坑是SDK路径带中文和空格。Makefile内部对路径的处理不如IDE智能,路径里只要有一个空格,就可能随机爆出“No such file or directory”,而且排查起来特别费时间。建立~/workspace这类纯英文目录,能避掉大部分低级问题。

第三个坑是虚拟机不装扩展包,USB串口透传不进去,导致烧录时找不到设备。这个问题在Windows宿主+Linux虚拟机的组合下几乎人人都会碰到,提前装好扩展包能省一个晚上。

第四个坑是忘记板子要进入下载模式。烧录工具连不上就怀疑驱动、怀疑板子、怀疑线材,其实只是BOOT按键没按,或者按的顺序不对。

第五个坑是编译成功但烧录后没有任何反应,然后怀疑自己代码有问题。先别急着改代码,确认板子是否从用户Flash启动。很多时候只是复位键没按,或者启动方式还停留在上次烧录的ISP模式。

5.2 我的几条实操建议

第一条建议:每次拿到新SDK,先花二十分钟把README完整读一遍,特别是“环境要求”和“快速开始”两个章节。很多问题都能在文档里找到答案,直接跳过去会花更多时间返工。

第二条建议:保留一个干净的编译日志文件。编译时可以执行:

make ... 2>&1 | tee build.log

一旦后面出现随机问题,对比前后日志能很快定位是工具链版本变了、SDK路径变了,还是代码改坏了。

第三条建议:不要在整个SDK里到处改东西。第一次接触时,尽量只改应用层代码和必要的板级配置;涉及到底层驱动、协议栈和链接脚本的修改,等熟悉整体结构之后再说。否则出了问题,你会分不清是自己的改动影响了全部,还是本来就有隐藏问题。

第四条建议:善用make clean。每次切换工具链版本、换分支、大改配置之后,先clean再全量编译。旧的目标文件和依赖关系偏移,是很多隐性问题的主要来源。

第五条建议:烧录后第一时间记录固件的编译时间和哈希值。比如:

sha256sum build/bs21e_sle_uart.hex

在板子上跑了一段时间后回来对照,能准确判断当前固件是不是最新版。这个习惯帮我排查过不少“我明明改了啊”的灵异事件。

最后再分享一个小技巧:日志输出别只盯着业务代码里的打印,可以把芯片启动早期打印的日期、版本号、编译标识也保留下来。这些信息在排查问题时是锚点,能帮你快速确认芯片运行时的固件版本、启动路径和配置来源。环境搭建这件事,本质上就是把你和芯片之间的链路打通,链路通了,后面所有开发才有基础。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进