2、开发环境搭建:交叉编译工具链安装、嵌入式Linux系统移植、Qt/Embedded环境配置
说实话,搭建开发环境这事儿,看着简单,但坑是真不少。我刚开始做呼吸机项目那会儿,光是在交叉编译工具链上就折腾了两天。后来总结出一个道理:环境搭得稳,后面才能睡得着觉。咱们一步步来。
2.1 交叉编译工具链安装
什么是交叉编译?说白了,就是在你的PC上编译出能在ARM板子上跑的程序。你的PC是x86架构,呼吸机主控板通常是ARM Cortex-A系列,这两者指令集不同,所以需要一套特殊的工具链。
核心要点:工具链版本必须与目标板内核匹配。我曾经因为用了高版本的gcc,编译出来的程序在板子上段错误,查了三天才发现是工具链ABI不兼容。
我个人习惯用Linaro提供的工具链,稳定且社区活跃。以ARM Cortex-A7为例,安装步骤如下:
# 下载Linaro交叉编译工具链
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 配置环境变量
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
小技巧:把环境变量写到 ~/.bashrc 里,这样每次打开终端就不用重新export了。我习惯在文件末尾加一行 source /opt/env_setup.sh,把所有交叉编译相关的变量集中管理。
验证是否安装成功:
arm-linux-gnueabihf-gcc --version
# 输出类似:arm-linux-gnueabihf-gcc (Linaro GCC 7.5.0) 7.5.0
嗯,看到版本号就说明工具链活了。这里要注意,有些新手会直接在板子上装gcc本地编译,这在资源紧张的嵌入式系统里是行不通的——你想想看,呼吸机的主控板通常只有256MB内存,跑个gcc编译能把系统卡死。
2.2 嵌入式Linux系统移植
系统移植,就是把Linux内核、根文件系统、设备树这些东西,搬到你的目标板上。呼吸机对实时性要求高,我建议用Linux内核的PREEMPT_RT补丁。
移植步骤大致分四步:
- 编译内核——配置适合呼吸机的内核选项
- 制作根文件系统——用Buildroot或Yocto
- 编写设备树——描述硬件资源
- 烧录启动——通过SD卡或NAND Flash
以我常用的i.MX6ULL平台为例:
# 下载内核源码
git clone https://github.com/embeddedlinux/linux-imx.git -b imx_4.19.35_1.1.0
# 配置内核(使用呼吸机专用配置)
make imx_v7_defconfig
make menuconfig # 这里要开启PREEMPT_RT和SPI、I2C驱动
# 编译内核
make -j4 zImage
make -j4 dtbs
注意:呼吸机的显示屏幕通常通过SPI或RGB接口连接,内核配置里一定要把对应的显示驱动选上。我遇到过有人忘了配LCD驱动,结果屏幕死活点不亮,还以为是硬件坏了。
根文件系统我推荐用Buildroot,轻量且容易定制。配置时记得选上Qt/Embedded的运行时库:
# 在Buildroot配置中
Target packages → Graphic libraries and applications → Qt5 → 选中 qt5base, qt5declarative
# 编译
make
编译完成后,你会得到四个关键文件:zImage(内核)、.dtb(设备树)、rootfs.tar(根文件系统)、u-boot.imx(引导程序)。把它们烧到SD卡上:
sudo dd if=u-boot.imx of=/dev/sdb bs=1k seek=1
sudo dd if=zImage of=/dev/sdb1
sudo dd if=imx6ull-14x14-evk.dtb of=/dev/sdb1
sudo tar -xvf rootfs.tar -C /mnt/sd
2.3 Qt/Embedded环境配置
Qt/Embedded,现在叫Qt for Embedded Linux,是呼吸机界面开发的核心。为什么选它?因为Qt的QML做动画效果很流畅,呼吸机上的波形显示、报警动画都需要它。
配置步骤:
# 下载Qt源码
wget https://download.qt.io/archive/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz
# 解压并配置交叉编译
tar -xvf qt-everywhere-src-5.15.2.tar.xz
cd qt-everywhere-src-5.15.2
# 配置(关键参数)
./configure -prefix /opt/qt5.15.2-arm \
-xplatform linux-arm-gnueabihf-g++ \
-device linux-imx6-g++ \
-no-opengl \
-eglfs \
-no-xcb \
-qt-libpng \
-qt-libjpeg \
-qt-freetype \
-no-gtk \
-opensource \
-confirm-license \
-nomake examples \
-nomake tests \
-skip qtwebengine
为什么关掉OpenGL?呼吸机的主控芯片通常没有GPU,用eglfs(EGL文件系统)模式就够了。我刚开始不懂,开了OpenGL,结果编译出来的Qt在板子上跑不起来,报错说找不到GPU驱动。
编译安装:
make -j4
make install
安装完成后,把/opt/qt5.15.2-arm整个目录拷贝到板子的根文件系统里。然后在板子上设置环境变量:
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_WIDTH=800
export QT_QPA_EGLFS_HEIGHT=480
export QT_QPA_EGLFS_PHYSICAL_WIDTH=154
export QT_QPA_EGLFS_PHYSICAL_HEIGHT=86
export LD_LIBRARY_PATH=/opt/qt5.15.2-arm/lib:$LD_LIBRARY_PATH
避坑指南:屏幕尺寸参数一定要和你的硬件匹配。我曾经因为写错了物理尺寸,导致触摸坐标偏移,点按钮A却触发了按钮B。后来用ts_calibrate校准了一下才解决。
最后,写个简单的测试程序验证一下:
# test.cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel label("Hello, Ventilator!");
label.show();
return app.exec();
}
# 交叉编译
arm-linux-gnueabihf-g++ -o test test.cpp -I/opt/qt5.15.2-arm/include -L/opt/qt5.15.2-arm/lib -lQt5Core -lQt5Gui -lQt5Widgets
# 拷贝到板子上运行
./test
如果屏幕上出现了"Hello, Ventilator!",恭喜你,环境搭建成功了。接下来就可以正式开始写呼吸机的界面了。
嗯,总结一下今天的内容:工具链是基础,系统移植是骨架,Qt环境是血肉。这三样东西搭好了,后面的开发就会顺畅很多。我见过太多人卡在环境搭建这一步,其实只要按照步骤来,别跳步,基本不会出大问题。