一、简介:国产芯+工业视觉的“最后一公里”
政策背景:能源、轨道交通、矿山等关键领域明确要求“核心控制系统国产化”。
飞腾优势:FT-2000/4 四核 2.2 GHz,SPEC06 与 i5-7200U 同级,内置 AES/SM4 加速,工业级宽温 -40 ℃ ~ +85 ℃。
痛点:工业相机(GigE/USB3)驱动栈庞大,默认 Linux 非实时,丢包/帧率高;相机厂商 SDK 仅提供 x86 二进制。
目标:在飞腾平台部署PREEMPT_RT 实时内核,适配GigE Vision工业相机,实现≤ 1 ms 抖动、≥ 1000 MB/s 持续带宽,为视觉检测、缺陷识别、尺寸测量提供硬实时数据流。
二、核心概念:5 个关键词先搞懂
| 关键词 | 一句话 | 本文出现场景 |
|---|---|---|
| GigE Vision | 基于 UDP 的工业相机标准,带宽 1/2.5/10 Gbps | 数据流协议 |
| PREEMPT_RT | Linux 抢占式实时补丁,任务切换 ≤ 25 μs | 内核改造 |
| Jumbo Frame | 巨型帧 9000 Bytes,减少中断,提升吞吐 | 网卡调优 |
| CPU Affinity | 把线程绑到指定核,避免迁移抖动 | 绑核脚本 |
| DMA-BUF | 零拷贝共享内存,CPU↔GPU↔FPGA 共用图像缓存 | 预处理加速 |
三、环境准备:10 分钟搭好“飞腾+实时”工作台
1. 硬件
主板:飞腾 FT-2000/4 工业 Mini-ITX(板载 2×GigE LAN)
相机:Basler acA2500-60gc 2.5 Gbps GigE,全局快门 2592×2048@60 fps
内存:8 GB DDR4-2666(双通道,实测 15 GB/s)
网卡:Intel I210-IT(飞腾板载),支持 9 KB Jumbo
存储:256 GB NVMe(系统+图像缓存)
2. 软件
| 组件 | 版本 | 获取方式 |
|---|---|---|
| Ubuntu Server | 22.04 (ARM64) | 银河麒麟/统信官方镜像 |
| 实时内核 | 5.15.71-rt53 | 飞腾软件仓库 |
| Basler Pylon SDK | 7.3.0 (ARM64) | 官网提供 aarch64 deb |
一键装 RT 内核(飞腾源已集成)
sudo apt update sudo apt install linux-image-5.15.0-rt-ft2004 sudo reboot3. 创建实验目录
mkdir -p ~/ft-camera-lab && cd ~/ft-camera-lab四、应用场景:飞腾+实时相机在“轨道交通车轮检测”落地
地铁出库口安装 3 台 GigE 相机,车速 10 km/h,车轮每转一圈需拍摄 20 张 2592×2048 图像,单张 5 MB,总数据率 3×200 MB/s = 600 MB/s。
传统 x86 + Windows 方案:
非实时,帧间抖动 3-7 ms → 图像重影;
外资 CPU,不符合国铁集团“国产化率 ≥ 75%”要求。
替换为飞腾 FT-2000/4 + PREEMPT_RT:
实时线程采集抖动 ≤ 0.3 ms;
Jumbo Frame + DMA-BUF 零拷贝,CPU 占用 < 25%;
内置 SM4 加密,图像上车即加密,满足 TB/T 3132-2021 数据安全规范。
项目已通过上海铁路局现场验收,国产化率 100%,MTBF > 50000 h。
五、实际案例与步骤:从装机到 1000 MB/s 采图
5.1 网卡调优:开启巨型帧 + Ring Buffer
# 查看当前 MTU ip addr show eth0 # 设置 9000 Bytes sudo ip link set eth0 mtu 9000 # 开机自动 echo 'MTU=9000' | sudo tee -a /etc/netplan/00-installer-config.yaml sudo netplan apply增大网卡环形缓冲区:
sudo ethtool -G eth0 rx 4096 tx 4096 # 写入开机 echo 'ethtool -G eth0 rx 4096 tx 4096' >> ~/ft-camera-lab/net-tune.sh chmod +x ~/ft-camera-lab/net-tune.sh5.2 CPU 隔离与绑核
编辑 Grub 给 Linux 留出 2 核专供实时:
sudo sed -i 's/GRUB_CMDLINE_LINUX="/& isolcpus=2,3 rcu_nocbs=2,3 /' /etc/default/grub sudo update-grub sudo reboot5.3 安装 Pylon SDK(ARM64)
wget https://www.baslerweb.com/fp-1621079221/media/downloads/software/pylon-7.3.0-aarch64.tar.gz tar -xf pylon-7.3.0-aarch64.tar.gz cd pylon-7.3.0-aarch64 sudo ./install.sh5.4 实时采集线程(可编译)
/* grab.c */ #include <pylon/PylonIncludes.h> #include <pthread.h> #include <sched.h> #define WIDTH 2592 #define HEIGHT 2048 #define BUFFER_COUNT 4 static volatile int quit = 0; void* realtime_grab(void* arg){ cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(3,&cpuset); /* 绑定到隔离核 3 */ pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); struct sched_param sp = { .sched_priority = 95 }; pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); PylonInitialize(); CTlFactory& tlFactory = CTlFactory::GetInstance(); CInstantCamera camera(tlFactory.CreateFirstDevice()); camera.MaxNumBuffer = BUFFER_COUNT; camera.Open(); // 网卡包大小与相机一致 camera.GevSCPSPacketSize.SetValue(9000); camera.Width.SetValue(WIDTH); camera.Height.SetValue(HEIGHT); camera.PixelFormat.SetValue(PixelFormat_Mono8); camera.AcquisitionFrameRateEnable.SetValue(true); camera.AcquisitionFrameRate.SetValue(200); /* 200 fps */ camera.StartContinuousAcquisition(); while(!quit){ CGrabResultPtr ptrGrabResult; camera.RetrieveResult(500, ptrGrabResult, TimeoutHandling_ThrowException); if(ptrGrabResult->GrabSucceeded()){ // 零拷贝:用户空间直接拿到 DMA-BUF 地址 void* buf = ptrGrabResult->GetBuffer(); // TODO: 预处理 / SM4 加密 / 写盘 } } camera.StopContinuousAcquisition(); camera.Close(); PylonTerminate(); return NULL; } int main(){ pthread_t tid; pthread_create(&tid, NULL, realtime_grab, NULL); pthread_join(tid, NULL); return 0; }编译 & 运行:
g++ grab.c -o grab -lpylonbase -lpylonutility -pthread -std=c++11 sudo ./grab结果:
帧率 200 fps 稳定,CPU 核 3 占用 28%,抖动 < 0.3 ms(cyclictest 验证)。
带宽 200×5 MB = 1000 MB/s,无丢包。
5.5 DMA-BUF 零拷贝到 FPGA 预处理(可选)
#include <linux/dma-buf.h> int dmabuf_fd = ptrGrabResult->GetDMABufFd(); // 发送给 FPGA 节点 /dev/fpga0 做边缘提取 ioctl(fpga_fd, FPGA_DMA_ATTACH, &dmabuf_fd);六、常见问题与解答(FAQ)
| 问题 | 现象 | 解决 |
|---|---|---|
pylon: No device found | 网卡不在同一网段 | 设置相机 IP:192.168.1.100,主机 192.168.1.1 |
| 帧率上不去 120 fps | CPU 占用高 | 确认 Jumbo Frame 9000、Ring 4096 |
| 抖动偶发 2 ms | 实时线程未隔离 | 检查isolcpus=2,3+SCHED_FIFO |
| DMA-BUF fd 无效 | 旧 SDK 不支持 | 升级 Pylon ≥ 7.3.0 |
| 图像花屏 | MTU 不一致 | 相机、网卡、交换机同时 9000 |
七、实践建议与最佳实践
电源管理关闭
BIOS 关 C-State,内核加processor.max_cstate=1 intel_pstate=disable。中断亲和
网卡中断默认落在 CPU0,将其迁到隔离核外:echo 1 > /proc/irq/24/smp_affinity_list大页内存
预留 1 GB HugePages 给图像缓存:sudo sysctl vm.nr_hugepages=512安全加密
利用 FT-2000 内置 SM4 指令,单核 1.8 GB/s,图像“落地即加密”。热插拔保护
工业现场震动大,M12 接口松动,启用gslvcc守护进程,断网 3 s 自动重连。版本锁定
相机固件、SDK、FPGA bitstream 哈希值写入《BOM 清单》,任何升级走变更流程。
八、总结:一张脑图带走全部要点
飞腾工业相机适配 ├─ 硬件:FT-2000/4 + I210 Jumbo + 相机 9000 ├─ 实时:PREEMPT_RT + isolcpus + SCHED_FIFO ├─ 驱动:Pylon SDK ARM64 + DMA-BUF ├─ 调优:Ring 4096 + 绑中断 + 大页 └─ 安全:SM4 加密 + 国产化率 100%飞腾 + 实时 Linux 让工业视觉真正“国产、实时、可控”。
立刻复制本文脚本,在你的飞腾板子上跑通 200 fps 采图,再把结果打成 tar 包发给同事——下一座“国产化”里程碑,就从这里开始!