2、开发环境搭建:Linux/Windows下的NuttX编译环境、工具链安装、NSH调试
说实话,搭建开发环境这件事,看着简单,但坑是真不少。我见过太多新手卡在这一步,折腾一整天连个Hello World都跑不起来。今天我就把压箱底的经验掏出来,带你一步步搞定NuttX的编译环境。
2.1 环境选择:Linux还是Windows?
我个人习惯用Linux,尤其是Ubuntu 20.04或22.04 LTS。为什么?因为NuttX的官方CI就是跑在Ubuntu上的,兼容性最好。你想想看,如果连官方测试环境都出问题,那得多闹心。
当然,Windows也能用。我有个同事就是Windows死忠粉,他用WSL2(Windows Subsystem for Linux 2)跑NuttX,效果也不错。但注意,别用原生的Windows命令行——那玩意儿对嵌入式工具链的支持太差了。
我的建议:
- 首选:Ubuntu 20.04/22.04 原生安装
- 次选:Windows + WSL2(Ubuntu 20.04)
- 不推荐:原生Windows CMD/PowerShell
2.2 工具链安装:别踩这些坑
NuttX支持多种架构,ARM、RISC-V、x86都有。这里我以最常用的ARM Cortex-M系列为例,讲讲工具链怎么装。
2.2.1 安装ARM GCC工具链
别去官网手动下载!用包管理器最省心。在Ubuntu下,我一般这么干:
# 添加ARM工具链的PPA源
sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa
sudo apt update
# 安装gcc-arm-none-eabi
sudo apt install gcc-arm-none-eabi
# 验证安装
arm-none-eabi-gcc --version
嗯,这里要注意。我曾经遇到过一个问题:系统自带的gcc-arm-none-eabi版本太老,编译NuttX新版本时会报错。所以建议装完后再确认一下版本号,至少要在 10.3-2021.10 以上。
避坑指南:我曾经在Ubuntu 18.04上直接apt install,结果装了个6.x的老版本。编译时各种奇奇怪怪的链接错误,折腾了两天才发现是工具链版本问题。所以,一定要用PPA源或者手动下载最新版。
2.2.2 安装其他依赖
除了编译器,NuttX还需要一些辅助工具。我列个清单,你照着装就行:
sudo apt install \
bison flex gettext texinfo \
libncurses5-dev libncursesw5-dev \
gperf automake libtool \
pkg-config build-essential \
u-boot-tools
这些工具干嘛用的?说白了,bison和flex是解析配置文件的,ncurses是给menuconfig提供界面的。你不需要全记住,但少一个都可能编译失败。
2.3 获取NuttX源码
源码管理这块,NuttX已经从SVN迁移到Git了。现在都是用GitHub来管理:
# 克隆主仓库
git clone https://github.com/apache/nuttx.git nuttx
# 克隆应用仓库(里面有很多示例和工具)
git clone https://github.com/apache/nuttx-apps.git apps
# 注意:nuttx和apps要放在同一级目录下
ls -la
# 输出应该类似:
# drwxr-xr-x apps/
# drwxr-xr-x nuttx/
为什么强调同一级目录?因为NuttX的构建系统默认会在../apps找应用代码。我第一次用的时候没注意,把apps放到了别处,结果编译时一直报找不到头文件。嗯,这种低级错误,犯过一次就记住了。
2.4 配置与编译:第一次跑起来
好,现在工具链和源码都齐了。我们来编译一个最简单的例子——在QEMU上跑NuttX。
2.4.1 配置工程
NuttX用make menuconfig来配置,跟Linux内核很像:
cd nuttx
# 先加载一个默认配置(这里用QEMU的Cortex-M3模拟器)
make distclean
tools/configure.sh -l qemu-armv7m:nsh
# 打开配置界面(可选,新手可以先跳过)
make menuconfig
-l参数什么意思?我解释一下:它表示加载本地配置。如果不加,会从远端拉配置,速度慢不说,还可能因为网络问题失败。
2.4.2 编译
# 开始编译
make -j$(nproc)
# 编译成功后,会生成 nuttx.bin 和 nuttx.elf
ls -la nuttx.bin
如果一切顺利,你会看到类似这样的输出:
LD: nuttx
CP: nuttx.hex
CP: nuttx.bin
arm-none-eabi-objcopy -O binary nuttx nuttx.bin
看到LD: nuttx这行,就说明链接成功了。我第一次看到这个输出时,心里那个激动啊——虽然只是个空壳系统,但毕竟是自己亲手编译出来的。
小技巧:如果编译过程中报错,别慌。先看错误信息的前几行,大部分问题都是头文件路径不对或者工具链版本不匹配。我一般会先执行make clean再重新编译,有时候能解决一些奇怪的问题。
2.5 NSH调试:与NuttX对话
NSH(NuttShell)是NuttX的命令行交互界面。说白了,就是嵌入式版的bash。编译成功后,我们来试试怎么用。
2.5.1 在QEMU中运行
# 安装QEMU(如果还没装)
sudo apt install qemu-system-arm
# 启动NuttX
qemu-system-arm \
-M lm3s6965evb \
-kernel nuttx.bin \
-nographic \
-serial mon:stdio
启动后,你会看到NuttX的启动日志,最后出现一个nsh>提示符。恭喜,你已经成功进入了NuttX的Shell!
2.5.2 常用NSH命令
NSH的命令跟Linux Shell很像,但更精简。我列几个常用的:
| 命令 | 功能 | 示例 |
|---|---|---|
ls |
列出文件 | ls /dev |
cd |
切换目录 | cd /etc |
cat |
查看文件内容 | cat /etc/version |
ps |
查看进程 | ps |
free |
查看内存 | free |
help |
查看帮助 | help |
试试输入help,你会看到所有支持的命令列表。我个人最喜欢ps命令——它能让你直观地看到NuttX的任务调度情况,对理解RTOS很有帮助。
2.5.3 调试技巧:用printf大法
在嵌入式开发中,串口输出是最直接的调试手段。NuttX里用syslog来打印日志:
#include <nuttx/syslog/syslog.h>
void my_function(void)
{
syslog(LOG_INFO, "Hello from NuttX! Current tick: %lu\n",
clock_systime_ticks());
}
为什么不用printf?因为printf在NuttX里默认是重定向到文件系统的,而syslog直接走串口。你想想看,如果系统还没挂载文件系统,printf就废了。这个坑我踩过,所以现在习惯用syslog。
核心要点回顾:
- 环境选Linux(Ubuntu 20.04+),Windows用户用WSL2
- 工具链用PPA源安装,版本不低于10.3
- nuttx和apps要放在同一级目录
- 用
make menuconfig配置,make -j$(nproc)编译 - NSH调试用
syslog代替printf
好了,环境搭建就讲到这里。下一章我们会深入NuttX的任务管理,看看怎么创建和调度任务。到时候你会发现,今天搭的环境就是你的实验场——多跑多试,比看十遍文档都管用。