拓冰建站拓冰建站
首页 / 资讯中心 / 正文

nRF52832 GCC编译实战:从搭建环境到烧录调试

简介面向Nordic 52832低功耗蓝牙SoC开发者的GCC编译环境搭建资料合集涵盖从工具链安装、环境变量配置到固件编译下载的完整流程特别适合需要在Windows/Linux下使用开源工具链开发BLE物联网设备的嵌入式工程师。包体共27037个文件约255.99MB主要有C/C头文件与源码、Python辅助脚本、ARM交叉编译库与链接脚本、编译工具可执行程序以及HTML/PDF/文本说明文档各类型文件相互配套可直接用于搭建和验证编译环境。目前已有940人学习下载内容实用性得到一定认可。资料内含gcc-arm-none-eabi交叉编译工具链、MinGW运行环境以及Nordic相关GCC配置示例并配有详细的使用说明能帮助初学者少走弯路快速上手基于GCC的nRF52832开发流程。 如果你点进这篇文章大概率和我当初是一样的状态手里有一块nRF52832开发板官方资料推荐用SEGGER Embedded Studio或者Keil来编译可你就是想用GCC这套命令行工具链搞事情。原因可能有很多——想在VSCode里写代码、CI服务器上要跑自动化编译、不想装体积庞大的IDE、或者单纯想弄清楚从源码到hex文件之间到底发生了什么。无论你是哪一种nRF52832用GCC编译这条路完全走得通而且把环境折腾明白之后你对链接脚本、编译参数、固件结构的理解会比只会点IDE按钮深一个档次。这篇文章是我整理的一份资料合集以当时用的nRF5_SDK_17.1.0为例从零开始搭建GCC编译环境、理解SDK的Makefile、编译烧录第一个例程再到VSCode集成和常见坑的排查。内容不追求高深但保证每个步骤都能复现适合刚拿到开发板的小白也适合从IDE转向命令行的老手。1. 为什么我坚持用GCC编译nRF528321.1 官方工具链之外的另一种选择先对比一下nRF52832常见的开发方案你就明白GCC这套东西的价值在哪了。方案是否免费平台工程文件适合场景Keil MDK收费有试用版Windows.uvprojx国内很多教程默认用这个代码提示一般IAR EWARM收费Windows.ewp老项目常用但工程文件很难迁移SEGGER Embedded Studio免费Win/macOS/Linux.emProjectNordic官方主推开箱即用但编辑器体验一般GCC Makefile完全免费Win/macOS/LinuxMakefile命令行构建、CI集成、VSCode等任意编辑器我的实际感受是SEGGER Embedded Studio虽然开箱即用但它把编译参数、链接脚本、软设备地址这些东西都藏在工程配置里了。一旦你想定制比如换一个软设备版本、改Flash布局、加入自己写的库SES的图形界面反而成了阻碍。而GCC Makefile方案里一切都以文本形式躺在Makefile和链接脚本里改了什么一目了然放进Git里也能方便地做版本对比。还有一个现实场景是编译服务器。我后来做CI流水线时服务器是Linux无界面环境总不可能在上面装一个SES吧而GCC工具链用命令行一条命令就能部署项目代码拉下来直接make -j4就可以批量出固件。这种能力是IDE方案给不了的。1.2 GCC的编译流程值得花十分钟了解很多初学单片机的人有个误区点一下Build按钮固件就出来了。但GCC的编译过程其实分成四个阶段搞清楚这个对排查问题特别有帮助。第一个阶段是预处理编译器展开所有#include和#define。第二个阶段是编译把预处理后的C代码翻译成汇编。第三个阶段是汇编把汇编翻译成机器指令的目标文件.o文件。最后一个阶段是链接把所有目标文件和库文件合并按照链接脚本分配地址生成最终的hex/elf。在命令行下你随时可以用类似arm-none-eabi-gcc -E main.c -o main.i查看预处理结果用-S获得汇编用-c只编译不链接。有人用gcc -c -e -dd -o main.dd main.c这类命令做分步实验原理都是这套。搞清楚这个顺序后遇到报错就能快速判断是发生在哪个阶段找不到头文件是预处理阶段的事语法错误是编译阶段的事undefined reference则是链接阶段的事排查思路完全不一样。2. 动手之前必须搞懂的背景知识2.1 nRF52832、SDK和软设备的关系nRF52832是一颗Cortex-M4F内核的低功耗蓝牙SoC主频64MHz512KB Flash和64KB RAMxxAA版本。Cortex-M4F的“F”指的是带硬件浮点单元FPU这直接影响后面GCC编译参数里的浮点选项。nRF5 SDK是Nordic官方提供的软件开发套件里面包含了协议栈源码、外设驱动库、例程工程以及一个很关键的组成部分——SoftDevice软设备。SoftDevice是Nordic预先编译好、以hex文件形式提供的蓝牙协议栈用户程序编译的时候并不链接它但地址空间必须给协议栈留出位置。烧录时也分两步先烧SoftDevice再烧应用固件。很多GCC编译问题的根源就出在对SoftDevice和应用的Flash/RAM地址划分不理解上。以nRF52832最常见的s132软设备为例在SDK 17.1.0里它的hex文件通常位于components/softdevice/s132/hex/目录下文件名类似于s132_nrf52_7.3.0_softdevice.hex。这个协议栈会被烧录在Flash的最起始位置占用的地址范围大约从0x00000000到0x00026000所以应用程序的起始地址就不能是0x0而是0x00026000。RAM同理软设备会占用从0x20000000开始的一段RAM具体大小取决于版本我用的7.3.0大概是从0x20002608开始才是应用可用的RAM。这些数值不需要你背但要懂得看链接脚本。2.2 工具链由哪些部分组成一套可用的GCC编译环境不只是装个编译器那么简单实际由四个部分组成交叉编译器arm-none-eabi-gcc负责把C代码编译成ARM Cortex-M的机器码。构建工具makeGNU Make负责解析Makefile里的依赖关系并调用编译器。烧录和命令行工具nrfjprog来自Nordic官方出品的nRF Command Line Tools负责擦除、烧录、读取芯片。调试驱动和调试器SEGGER J-Link驱动配合J-Link调试器使用。由于nRF52832是ARM内核我们不能直接用PC上的gcc来编译而必须用针对嵌入式ARM的交叉编译器。注意“交叉”这个词意思是编译器运行在x86的PC上但生成的目标代码是ARM架构的。3. 一步一步搭建GCC编译环境3.1 安装ARM GCC工具链从ARM官方下载GNU Arm Embedded Toolchain也就是arm-none-eabi-gcc。Windows平台建议下载.exe安装包安装时勾选把bin目录加入环境变量PATH。不过我个人反而推荐下载zip压缩包解压到一个固定路径比如C:\arm-gcc然后手动把C:\arm-gcc\bin加入PATH。好处是以后想换版本只需要换目录不用走卸载程序多版本共存也方便。Linux平台下载tar.xz包解压到/opt下然后编辑~/.bashrc添加export PATH/opt/gcc-arm-none-eabi-10.3-2021.10/bin:$PATH source ~/.bashrc如果用Ubuntu这类有网络的系统直接sudo apt install gcc-arm-none-eabi也能装但版本可能偏旧。离线环境则可以从官网下载rpm安装包用rpm -ivh命令离线安装。装完务必验证版本arm-none-eabi-gcc --version如果显示的还是旧版本多半是PATH里旧版本的路径排在前面或者shell缓存了旧的命令路径执行hash -r刷新缓存再用which arm-none-eabi-gcc确认到底调用的是哪个路径下的编译器。这里有一个很多人都会踩的坑电脑上装了多个版本GCC工具链明明升级了新版但一运行arm-none-eabi-gcc --version显示的依然是旧版。主要原因就是PATH顺序不对。Windows下打开“环境变量编辑器”检查PATH中不同GCC目录的排列顺序把新版本放前面Linux下用which -a arm-none-eabi-gcc查看所有候选路径。3.2 安装make和nRF命令行工具Windows上的make安装有点讲究。SDK的Makefile是基于GNU Make的所以不能用微软自己的nmake。我比较推荐用MSYS2安装启动后执行pacman -S make然后终端里用的命令是mingw32-make。如果你更喜欢命令就叫make可以把C:\msys64\usr\bin里的make.exe复制到任意一个在PATH中的目录下或者干脆在终端里设置别名。macOS比较简单装了Homebrew后brew install make即可注意GNU make会被安装为gmake你可以在SDK的Makefile调用时用gmake或者做个软链接。nRF命令行工具是搞nRF52板子必备的从Nordic官网下载对应安装包。Windows装完、Linux解压后把bin目录加入PATH。验证nrfjprog --version这个工具包里其实还带了mergehex等实用软件后面合并多个hex文件时会用到。3.3 准备SDK和例程工程下载nRF5_SDK_17.1.0解压到一个纯英文路径下切记路径里不要出现中文和空格否则Windows下的make很容易出幺蛾子。SDK目录非常大刚开始你会觉得无从下手但只要关注两个地方就行components目录存放所有驱动和协议栈源码examples目录存放各种例程。我们以经典的examples/ble_peripheral/ble_app_uart为例这个例程实现了通过蓝牙透传串口数据的功能是大多数人的入门选择。例程目录下有几个子目录对应不同开发板和软设备组合。nRF52832的开发板通常是pca10040软设备是s132所以我们要找的路径就是examples/ble_peripheral/ble_app_uart/pca10040/s132/gcc/这个gcc目录里放着Makefile这就是我们所有编译工作的核心。4. 用Makefile编译第一个例程4.1 读懂SDK自带的Makefile打开pca10040/s132/gcc目录下的Makefile你会发现内容不算多SDK把大量的公共逻辑都封装在components/toolchain/gcc/Makefile.common里了。我们只需要关注几个关键变量。先来看与我之前讲解对应的关键片段实际上SDK自带的更复杂这里做了精简说明PROJECT_NAME : ble_app_uart TARGETS : nrf52832_xxaa OUTPUT_DIRECTORY : _build SDK_ROOT : $(abspath ../../../../../..) SOFTDEVICE : s132 # 链接脚本 LINKER_SCRIPT : ble_app_uart_gcc_nrf52.ld # 编译参数 CFLAGS -mcpucortex-m4 -mthumb -mabiaapcs CFLAGS -mfloat-abihard -mfpufpv4-sp-d16 CFLAGS -DNRF52832_XXAA CFLAGS -DBOARD_PCA10040 CFLAGS -DS132 CFLAGS -DSOFTDEVICE_PRESENT CFLAGS -DSWI_DISABLE # 头文件路径 CFLAGS -I$(SDK_ROOT)/components/softdevice/s132/headers # ... include $(SDK_ROOT)/components/toolchain/gcc/Makefile.common这里几个变量是重点。TARGETS定义了目标芯片型号nrf52832_xxaa对应512KB Flash版本的nRF52832。SDK_ROOT是SDK的根目录路径原厂默认用相对路径从gcc目录往上跳6级刚好到达SDK根目录但这个写法要求整个SDK目录结构不能移动。如果你把例程复制到别处要么修改相对路径要么直接改成绝对路径比如SDK_ROOT : /home/user/nRF5_SDK_17.1.0。编译参数里的-mcpucortex-m4 -mthumb告诉编译器目标内核是Cortex-M4且使用Thumb指令集。-mfloat-abihard -mfpufpv4-sp-d16启用硬件浮点单元这正好对应我之前说nRF52832是Cortex-M4F这一点。如果你把float-abi设成soft程序也能跑但浮点运算会慢很多而且如果整个工程里有人用了硬浮点函数库链接时还会报错。4.2 修改配置并执行编译打开命令行切到gcc目录执行编译make -j4-j4表示启用4个并行编译任务能明显加快速度。如果你还没修改SDK_ROOT第一次编译大概率会报错找不到Makefile.common这时候直接把Makefile里的SDK_ROOT : $(abspath ../../../../../..)换成你的SDK绝对路径就行。也可以不改文件每次编译时临时指定make -j4 SDK_ROOT/你的路径/nRF5_SDK_17.1.0编译成功后_build目录下会出现这些文件nrf52832_xxaa.hexIntel HEX格式的固件烧录用这个。nrf52832_xxaa.elf带调试信息的可执行文件在线调试要用它。nrf52832_xxaa.map链接映射文件里面记录了每个函数、每个变量被分配到哪个地址排查问题极有用。nrf52832_xxaa.bin纯二进制镜像某些烧录工具需要。查看固件占用的Flash和RAM大小arm-none-eabi-size _build/nrf52832_xxaa.elf这个命令会输出text/data/bss三列数值text加data就是占用的Flash空间data加bss是运行时占用的RAM空间。迭代开发时我习惯编译完扫一眼这个数值心里对余量有数。如果想清理重新编译执行make clean想连依赖文件一起清掉就make pristine后者在我更换编译选项后必用一次避免一些莫名其妙的增量编译问题。4.3 编译报错怎么快速定位命令行编译的错误信息比IDE原始但定位起来并不难掌握一个原则不要看最后一行要看第一条error之后紧跟的那个文件路径和行号。下面这些是我遇到过最多的错误类型。找不到头文件报错是fatal error: xxx.h: No such file or directory。这种情况就是Makefile里-I参数的头文件路径不全一般是缺少某个SDK组件路径或者你添加了自定义模块但忘了加include路径。链接阶段报undefined reference to xxx说明某个函数声明了但没找到实现。最常见的原因是相应的.c文件没有加入编译依赖。在SDK的Makefile里源文件是通过$(wildcard ...)方式自动收集的如果你自己添加了源文件目录需要在SRC_FILES或类似的变量里补上。还有一种情况是配合静态库时报一堆找不到符号那就要检查Makefile里的LIB_FILES变量要把.a库文件路径和对应的-l参数加对。GCC链接库这件事本质上就是告诉链接器去哪儿找符号路径不对符号自然找不到。5. 烧录、调试与VSCode集成5.1 烧录分两步先软设备后应用编译只是上半场把固件烧进芯片才算跑通。连接好J-Link和开发板先烧录SoftDevice。建议直接用SDK自带的最省事方式在gcc目录下执行make flash-softdevice这个目标会调用nrfjprog擦除整个芯片然后把软设备的hex烧进去。如果你想手动操作对应的命令是nrfjprog --program components/softdevice/s132/hex/s132_nrf52_7.3.0_softdevice.hex --chiperase -f nrf52注意--chiperase参数它会擦除整片Flash。所以如果芯片里已经烧了重要的生产固件千万别直接执行这个命令数据会全没。接下来烧录应用固件nrfjprog --program _build/nrf52832_xxaa.hex --sectorerase -f nrf52 nrfjprog --reset -f nrf52这次用的是--sectorerase只擦除应用所在的扇区不会动已经烧好的SoftDevice。两步的顺序不能反如果先烧应用后烧软设备软设备会把应用覆盖掉。分步流程走通之后完全可以在Makefile里加一个flash-all目标一键完成两步烧录。5.2 VSCode里配好代码提示、编译任务和调试用VSCode写nRF52代码体验确实比SES舒服但需要配置三个文件。第一个是.vscode/c_cpp_properties.json负责代码补全和语法检查。关键是让IntelliSense理解我们的编译宏和头文件路径{ configurations: [ { name: nRF52, compilerPath: C:/arm-gcc/bin/arm-none-eabi-gcc.exe, defines: [ NRF52832_XXAA, BOARD_PCA10040, S132, SOFTDEVICE_PRESENT, CONFIG_GPIO_AS_PINRESET ], includePath: [ ${workspaceFolder}/**, D:/nRF5_SDK_17.1.0/components/**, D:/nRF5_SDK_17.1.0/modules/**, D:/nRF5_SDK_17.1.0/integration/nrfx/** ] } ], version: 4 }defines里的宏要和Makefile里保持一致不然会出现在Makefile中编译通过但VSCode里疯狂标红的情况。includePath里的SDK路径按你自己的实际情况改。第二个是.vscode/tasks.json把编译变成快捷键触发的任务{ version: 2.0.0, tasks: [ { label: build, type: shell, command: make, args: [-j4], options: { cwd: ${workspaceFolder}/examples/ble_peripheral/ble_app_uart/pca10040/s132/gcc }, group: { kind: build, isDefault: true } } ] }第三个是.vscode/launch.json配合Cortex-Debug插件实现在VSCode里打断点调试{ version: 0.2.0, configurations: [ { name: nRF52 Debug, type: cortex-debug, request: launch, servertype: jlink, device: nRF52832_xxAA, interface: swd, executable: ${workspaceFolder}/examples/ble_peripheral/ble_app_uart/pca10040/s132/gcc/_build/nrf52832_xxaa.elf, runToEntryPoint: main } ] }安装好Cortex-Debug插件、确保J-Link驱动已安装按F5就能进入调试。可以在main函数里打断点查看变量值这与之前nrfjprog命令行方式互为补充命令行处理批量烧录VSCode处理日常调试。6. 常见问题与排查技巧实录6.1 程序烧进去却跑不起来的地址陷阱这个坑我当年踩得极为深刻。烧录一切正常但程序上电后没有任何现象用调试器单步走会发现程序跑飞进HardFault。最后排查出来是SoftDevice版本和链接脚本不匹配。SDK 17.1.0中同一份例程的gcc目录下可能有多个链接脚本比如gcc_nrf52.ld和适配某个软设备版本的专用ld。如果你在Makefile里指定的是不匹配s132版本的链接脚本Flash和RAM起始地址就会算错。程序以错误地址启动后面所有外设初始化都会出问题。排查方法也不复杂烧录后用J-Link读回Flash内存看看0x00026000附近到底有没有程序。更简单的用一个官方没改过的例程直接编译烧录如果官方版本能跑、你的工程跑不了那就逐一比对Makefile改动重点检查LINKER_SCRIPT、CFLAGS里的宏定义是否与软设备版本匹配。6.2 工具链升级后编译还是旧版本“明明升级了GCC为什么编译时还是旧版本”这个问题不止一个人问过我。原因基本就两类。第一类是PATH顺序问题前面已经说过用which arm-none-eabi-gcc确认实际调用的是哪个路径。第二类是Makefile或构建脚本里直接硬编码了旧版本的绝对路径。这种情况常见于从网上拷贝的Makefile里面写着CC : /opt/gcc-arm-none-eabi-5.4.1/bin/arm-none-eabi-gcc之类的固定路径。建议要么删掉这种硬编码改成CC ? arm-none-eabi-gcc让系统PATH决定要么每次升级后同步修改Makefile中的路径。升级GCC后还可能遇到另一个问题新版编译器对C语言标准的实现更严格以前在旧版本下能编译通过的代码现在可能报一堆warning甚至error。比如隐式函数声明这类问题在旧GCC里是warning新GCC直接给error。这时候先别急着减编译选项把代码里那些隐患改掉反而是好事。6.3 J-Link连不上目标芯片nrfjprog执行时报Could not connect to target先别怀疑芯片坏掉按顺序排查测量开发板供电是否正常nRF52832是3.3V供电检查SWDIO、SWCLK、GND三条线是否接对尤其是GND必须可靠共地确认J-Link型号和驱动版本别太老旧老驱动有时不识别较新的nRF52832批次芯片。还有些情况是芯片被锁死了通常是因为代码里意外使能了读保护或者调试口复用。这时候用nrfjprog --recover可以解锁但必须明确这个命令会全片擦除Flash里的SoftDevice和应用都会消失。解锁后重新走一遍软设备应用烧录流程就能恢复。6.4 常见问题速查表现象可能原因处理建议make找不到Makefile.commonSDK_ROOT路径不对改成绝对路径或在make命令行指定SDK_ROOT编译报No such file or directory头文件路径缺 -I对照Makefile检查includePath补充SDK组件路径链接报undefined reference源文件未参与编译或库未链接检查SRC_FILES和LIB_FILES变量程序烧录成功但无现象链接脚本地址与SoftDevice不匹配确认LINKER_SCRIPT与软设备版本对应Cannot connect to target接线/供电/芯片锁定检查SWD接线和供电必要时nrfjprog --recover烧录时报Flash占用溢出Flash空间不够检查map文件裁剪无用功能或启用 -Wl,--gc-sectionsWindows下make执行异常路径中文/空格或make版本不兼容工程放到纯英文路径换GNU make版本最后再分享一点个人的折腾心得这套GCC环境搭好之后最大的收获并不是“摆脱了IDE”而是我终于看懂了固件的生成链路。看Makefile让我明白了编译参数如何影响最终产物看链接脚本让我理解了Flash和RAM的布局逻辑看map文件让我知道了每个函数被放到了哪里。这种掌控感是用图形界面点Build完全体会不到的。实际开发中我形成了一套固定习惯改任何配置前先make clean编译完就看一眼arm-none-eabi-size的输出烧录前用nrfjprog --memrd快速验证一下Flash关键地址的数据。这些操作花不了几秒钟但能在问题暴露前就发现端倪。如果你也想深入nRF52开发别嫌搭建环境麻烦这一下午的折腾绝对值得。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门