RIOT 系统 hello-world 示例深度解析:从嵌入式 Makefile 构建系统到板卡移植运行
2026/9/20 1:41:37 网站建设 项目流程
  • 物联网
  • 嵌入式
  • 操作系统
  • 实时系统

【免费下载链接】RIOT

RIOT - The friendly OS for IoT

项目地址:https://gitcode.com/GitHub_Trending/riot/RIOT
点击查看免费下载

本文以 RIOT 仓库中的 examples/basic/hello-world 官方示例为主体,系统讲解 RIOT 应用工程的目录结构、main.c入口程序,以及 RIOT 独特 Makefile 构建系统的核心变量(APPLICATIONBOARDRIOTBASEDEVELHELPQUIET等)的语义与底层实现,最终引导读者在 native 模拟平台与真实硬件板卡上完成编译、烧录与运行,为后续开发任意 RIOT 应用打下坚实基础。

一、示例概览:RIOT 应用的最小形态

hello-world是 RIOT 官方示例集中最基础的一个应用,位于仓库的 examples/basic/hello-world/ 目录。它的全部内容只有三个文件:

examples/basic/hello-world/ ├── Makefile # 应用构建配置(RIOT 构建系统的入口) ├── README.md # 官方说明文档 └── main.c # 应用入口源码

其作用正如 README 所述:在嵌入式应用中打印那句经典的Hello World!。这个示例的首要目的并不是演示 C 语言本身,而是让你完整走一遍 RIOT 应用的组织流程——应用如何命名、如何选择板卡、如何定位 RIOT 源码根目录、如何接入 RIOT 的 Makefile 构建系统。

在 RIOT 的 examples/basic 目录下,还并列着blinkydefaultfilesystemipc_pingpongsaultimer_periodic_wakeup等示例,它们与hello-world遵循完全相同的工程组织规范,因此掌握本示例就等于掌握了 RIOT 所有示例乃至自研应用的工程骨架。

二、入口源码 main.c:标准 C 与 RIOT 专属宏

main.c的完整内容如下(见 examples/basic/hello-world/main.c):

#include <stdio.h> int main(void) { puts("Hello World!"); printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD); printf("This board features a(n) %s CPU.\n", RIOT_CPU); return 0; }

这段代码看起来与任何 C 语言的入门示例无异,但其中暗含了 RIOT 的两个核心机制:

  1. main()是应用唯一入口:RIOT 与裸机程序一样,应用从main()开始执行。RIOT 内核在启动时会完成硬件初始化、调度器与线程系统的建立,然后调用应用的main()进入用户逻辑。
  2. RIOT_BOARDRIOT_CPU是编译期宏:它们并非 C 语言内置符号,而是 RIOT 构建系统在编译时通过预处理器注入的字符串宏。在 Makefile.include 中可以看到它们的定义方式:
BOARDDEF = $(call uppercase_and_underscore,$(BOARD)) CPUDEF = $(call uppercase_and_underscore,$(CPU)) CFLAGS += -DRIOT_APPLICATION=\"$(APPLICATION)\" CFLAGS += -DBOARD_$(BOARDDEF)=\"$(BOARD)\" -DRIOT_BOARD=BOARD_$(BOARDDEF) CFLAGS += -DCPU_$(CPUDEF)=\"$(CPU)\" -DRIOT_CPU=CPU_$(CPUDEF)

也就是说,当你以BOARD=native64构建时,编译器会自动获得-DBOARD_NATIVE64="native64" -DRIOT_BOARD=BOARD_NATIVE64以及对应的RIOT_CPU定义。因此无论在哪块板卡上编译,printf输出的都是当前构建目标的真实板卡名与 CPU 名——这正是同一份源码可以跨板卡运行的直接体现。

三、Makefile 核心变量详解:RIOT 构建系统的五个关键点

hello-world的 Makefile 全文如下:

# name of your application APPLICATION = hello-world # If no BOARD is found in the environment, use this default: BOARD ?= native # This has to be the absolute path to the RIOT base directory: RIOTBASE ?= $(CURDIR)/../../.. # Comment this out to disable code in RIOT that does safety checking # which is not needed in a production environment but helps in the # development process: DEVELHELP ?= 1 # Change this to 0 show compiler invocation lines by default: QUIET ?= 1 include $(RIOTBASE)/Makefile.include

README 中强调的五个要点,逐一对应如下:

1.APPLICATION:应用名称

应用必须有一个名字,惯例是与所在目录同名(这里是hello-world)。构建系统会以它为前缀生成可执行文件:默认输出为bin/$(BOARD)/$(APPLICATION).elf(ELF 规则见 Makefile.include)。此外,APPLICATION还会被注入为-DRIOT_APPLICATION=\"$(APPLICATION)\"宏,并作为应用模块application_$(APPLICATION)的名称参与链接(见 Makefile.include)。

2.BOARD:目标板卡

BOARD ?= native声明了默认板卡,其中?=表示仅当环境中未定义BOARD时才生效。因此你可以随时用命令行覆盖默认值:

make BOARD=msba2 # README 中的经典示例 make BOARD=nrf52840dk # 切换到 nRF52840DK make BOARD=samr21-xpro # 切换到 SAM R21 Xplained Pro

这一机制正是 RIOT "一次编写、处处编译" 的基石——同一份main.c与 Makefile,只需要更换BOARD变量即可面向不同硬件构建。

3.RIOTBASE:RIOT 根目录

RIOTBASE保存 RIOT 源码检出目录的绝对或相对路径。当应用位于 RIOT 仓库内部时,通常用$(CURDIR)(GNU Make 内置的当前目录变量)拼出相对路径:本示例位于仓库根目录下三级,因此是$(CURDIR)/../../..

值得一提的是,若你在 RIOT 仓库之外开发应用,可以不写这一行——因为 Makefile.include 会兜底:

RIOTBASE ?= $(_riotbase)

其中_riotbase基于LAST_MAKEFILEDIR(最后包含的 Makefile 所在目录,即Makefile.include自身所在目录)求值,从而自动推导出 RIOT 根目录。显式设置RIOTBASE则适用于把应用放在仓库内的场景。

4.DEVELHELP:开发期安全检查

DEVELHELP ?= 1开启 RIOT 的开发期辅助代码(断言、内存越界检测等安全检查)。这类检查在生产环境中不需要,但在开发阶段非常有价值。其底层实现在 Makefile.include:

DEVELHELP ?= 0 ifeq ($(DEVELHELP),1) CFLAGS += -DDEVELHELP endif

即当DEVELHELP=1时,向所有源文件注入-DDEVELHELP宏,RIOT 内核与模块据此启用额外的安全检查逻辑。发布正式产品前,可将其注释掉或置 0 以缩减代码体积。

5.QUIET:编译输出详略开关

QUIET取值为101隐藏冗长的编译命令行(默认,仅显示简洁摘要);0显示每条完整的编译器调用。其在 Makefile.include 的实现是:

QUIET ?= 1 QUIETER ?= 0 ifeq ($(QUIET),1) Q=@ # 抑制命令回显 MAKEFLAGS += --no-print-directory else Q= endif

构建规则中的每个命令都以$(Q)开头,Q@时命令不回显,为空时完整回显。需要排查编译参数(如确认-DRIOT_BOARD是否正确注入)时,执行make QUIET=0即可看到全部编译器调用。

6. 最后一行:接入构建系统

Makefile 的最后一行必须是include $(RIOTBASE)/Makefile.include。这一行将 RIOT 的整套构建系统(约 1139 行的核心逻辑:板卡解析、特性检查、模块依赖、链接规则、烧录与终端目标等)全部引入当前应用,此后你就能使用makemake flashmake term等一系列标准目标了。RIOT 要求它位于文件末尾,因为其内部规则会依赖应用 Makefile 中已定义的变量。

四、构建到运行:在 native 平台上的无硬件体验

BOARD=native(以及native64native32)是 RIOT 最具特色的板卡之一。按照 boards/native64/doc.md 的说明,native 板卡通过系统调用与信号在 API 层面模拟硬件,让你把完整的 RIOT 软件栈编译成本机进程直接运行,无需任何开发板。

在 hello-world 目录执行:

make # 默认 BOARD=native,自动选择 64/32 位变体

随后运行生成的可执行文件(native 的 "烧录" 就是直接运行进程):

make term

即可看到输出:

Hello World! You are running RIOT on a(n) native64 board. This board features a(n) native CPU.

make term实际调用的是 Makefile.include 中定义的终端目标,通过TERMPROG(native 下即应用进程本身)打开串口/终端。这样,即使没有硬件,你也能完成 RIOT 应用的开发、调试与逻辑验证——这也是学习本示例的最低成本路径。

五、面向真实硬件:交叉编译、烧录与终端

当需要部署到真实板卡时,只需覆盖BOARD。例如使用 STM32 平台(以nucleo-f401re为例)或 Nordic nRF 平台(nrf52840dk):

make BOARD=nucleo-f401re # 交叉编译 make BOARD=nrf52840dk flash # 编译并烧录 make BOARD=nrf52840dk term # 打开串口终端观察输出

流程要点:

  • 交叉编译:RIOT 会根据CPU自动选择对应的交叉工具链(GNU/LLVM),无需手工配置CC
  • 烧录make flash调用板卡对应的PROGRAMMER(如 OpenOCD、JLink、pyocd 等),烧录文件默认为$(BINDIR)/$(APPLICATION).elf
  • 串口终端make term通过TERMPROG(通常为 pyterm)连接板卡串口,你将在其中看到与 native 平台一致的Hello World!输出以及正确的板卡名。

例如以BOARD=nrf52840dk构建时,宏展开后printf将输出You are running RIOT on a(n) nrf52840dk board.,证明同一份源码在真实硬件上无需任何修改即可运行。

六、常用构建目标速查

接入Makefile.include后,hello-world 自动获得以下常用目标(定义见 Makefile.include):

命令作用
make默认目标all,编译并链接生成bin/$(BOARD)/$(APPLICATION).elf
make BOARD=<板卡>覆盖默认板卡后重新构建
make flash编译并烧录到目标板卡
make flash-only仅烧录(不重新编译)
make term打开串口/仿真终端
make debug启动调试器(需板卡支持)
make clean清理当前板卡的构建产物bin/$(BOARD)
make distclean清理全部板卡的构建产物
make QUIET=0显示完整编译器调用,便于排错
make print-size打印固件体积(text/data/bss)

七、小结

hello-world虽然只有两个源文件,却是理解 RIOT 应用开发范式的最佳起点:它完整展示了 RIOT 应用的目录组织、main.c入口约定、RIOT_BOARD/RIOT_CPU编译期宏注入,以及APPLICATIONBOARDRIOTBASEDEVELHELPQUIET五个核心 Makefile 变量的语义与底层实现。掌握这些内容后,无论是阅读 examples/basic 下的其他示例,还是从零编写自己的 RIOT 应用,你都能迅速上手——只需复制本目录骨架,修改APPLICATION名称与业务代码,再选定BOARD即可。

  • 物联网
  • 嵌入式
  • 操作系统
  • 实时系统

【免费下载链接】RIOT

RIOT - The friendly OS for IoT

项目地址:https://gitcode.com/GitHub_Trending/riot/RIOT
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询