1. 项目概述国产化浪潮下的实时数据采集新选择最近在做一个工业数据采集的项目客户对国产化、实时性和通道数都有硬性要求。传统的方案要么用X86工控机加PCIe采集卡成本高、功耗大要么用一些ARM核心板但多通道同步采集和实时处理能力又成了瓶颈。折腾了一圈最后我们把目光投向了RK3568这颗国产SoC再搭配一颗灵活可编程的FPGA搞出了一套性价比和性能都相当不错的多通道AD实时采集显示方案。今天就把这套方案的思路、踩过的坑和最终实现细节跟大家详细唠唠。简单来说这个方案的核心思想是“软硬协同各司其职”。RK3568作为主控负责运行Linux系统、人机交互界面HMI、网络通信以及复杂的数据分析和存储任务而FPGA则扮演一个高速、精准的“数据搬运工”和“预处理引擎”它直接与多路AD芯片模数转换器对接完成多通道信号的同步采集、数字滤波、初步运算并通过高速接口如PCIe或高速并行总线将规整后的数据高效地传递给RK3568。这样一来既发挥了ARM处理器在应用生态和通用计算上的优势又利用了FPGA在并行处理和实时性上的绝对长处非常适合需要多通道8路、16路甚至更多、高采样率、低延迟的工业现场数据采集与监控场景。如果你正在寻找一个替代传统工控机方案、追求更高集成度和更低成本的实时采集方案或者对信号处理、嵌入式Linux和FPGA协同开发感兴趣那这篇分享应该能给你一些直接的参考。方案里用到的RK3568和国产FPGA现在货源和资料都比以前好了很多自主可控程度高是个值得深入玩一玩的方向。2. 方案核心架构与选型思路为什么是RK3568FPGA这个组合不是凭空想出来的而是基于项目需求一步步推导出来的。我们的核心需求可以概括为至少16通道同步采集、每通道最高100KSPS采样率、实时波形显示、数据本地存储并支持网络上传、整体成本可控、开发周期不能太长。2.1 主控芯片RK3568的考量首先看主控。我们需要一个能跑Linux的处理器因为上层应用如Qt界面、数据库、Web服务在Linux下开发效率最高生态最成熟。但常见的树莓派类芯片接口和可靠性往往难以满足严苛的工业环境。RK3568是瑞芯微推出的一款中高端通用型SoC它的几个特点正好切中我们的需求性能与接口平衡四核Cortex-A55主频最高2.0GHz性能足以流畅运行嵌入式Linux和复杂的图形界面。它集成了丰富的接口双千兆以太网、多个USB、PCIe 2.1、SATA 3.0等为连接FPGA和外设提供了极大灵活性。强大的多媒体与显示能力内置独立的NPU约0.8Tops算力和GPUMali-G52虽然我们这个项目暂时用不到NPU做AI推理但强大的GPU对于多通道波形画面的流畅渲染至关重要。它支持双屏异显方便我们设计一个主显示界面和一个辅助监控界面。国产化与生态RK3568是国内厂商主导设计和推广的芯片供应链相对安全。更重要的是它的Linux内核主线支持度越来越好社区资源和商业SDK都比较丰富能显著降低底层系统移植的难度和风险。注意选择RK3568而不是更便宜的RK3328或RK3399主要是看中了其PCIe接口和更好的长期供货保障。PCIe对于实现与FPGA的高速数据通信目标带宽需达到数百MB/s是关键。2.2 协处理器FPGA的不可或缺性多通道、高实时性的AD采集是纯软件方案哪怕用实时Linux补丁很难完美解决的痛点。主要挑战在于中断延迟Linux系统本身不是硬实时系统即使使用高精度定时器或PREEMPT_RT补丁中断响应和处理仍有微秒级的不确定性对于严格同步的采样时刻控制是个挑战。CPU负载如果由CPU通过SPI或I2C去轮询读取多个AD芯片在高采样率下CPU会被完全拖垮无法进行其他任务。精确时序控制多通道采样需要精确的时钟同步这个用CPU软件时序很难保证。因此引入FPGA成了必然选择。我们选用了一款国产的安路科技的FPGA芯片具体型号根据逻辑规模和接口需求选定。FPGA在这里承担了核心的硬件任务多通道采集控制器FPGA内部实现多个并行的采集控制状态机为每个AD通道产生精确的采样时钟和读取时序确保所有通道在同一时刻被采样实现真正的同步。高速数据接口桥接FPGA一端通过并行总线或SPI接口连接多片AD芯片如ADI的AD7606系列它本身支持8通道同步采样另一端通过PCIe接口与RK3568通信。FPGA内部实现PCIe Endpoint硬核或软核并打包DMA引擎将采集到的数据块直接搬运到RK3568系统内存中无需CPU干预。实时预处理我们甚至在FPGA里加入了简单的预处理逻辑比如数字滤波FIR、量程转换、甚至FFT运算。这样传给RK3568的已经是“半成品”数据进一步减轻了CPU的负担。这种架构下RK3568的CPU只需要在FPGA通过中断告知“数据准备好了”之后去处理内存中已经存在的规整数据包即可采集过程的实时性由FPGA硬件保证软件层的压力大大减轻。2.3 整体数据流设计理解了芯片选型整个方案的数据流就清晰了采集端模拟信号 - 信号调理电路 - 多通道AD芯片 - FPGA同步控制、数据接收、预处理、打包- 通过PCIe DMA - RK3568系统内存的指定缓冲区。处理与显示端RK3568 CPU收到FPGA中断 - 从内存缓冲区读取数据包 - 解包、校验、存入环形缓冲区 - 显示线程从环形缓冲区取数据通过OpenGL或Qt的图形接口进行波形绘制刷新 - 同时存储线程将数据写入本地SSD通过SATA接口网络线程可通过TCP/IP将数据流或处理结果上传至上位机。这个流水线式的设计确保了从采集到显示、存储的各个环节都能高效并发执行。3. 硬件平台设计与关键细节方案定了接下来就是硬件实现。自己画板子固然自由度高但考虑到周期和可靠性我们选择了“核心板载板”的模式。3.1 核心板选型与接口定义我们采购了市面上成熟的RK3568核心板它通常集成了RK3568芯片、LPDDR4内存、eMMC存储和电源管理。选择时重点关注PCIe接口是否引出核心板的板对板连接器必须包含PCIe x1或x2的差分信号线。工业级温度范围项目用于工业现场必须选择支持-40°C ~ 85°C的工业级版本。供应商的Linux BSP支持是否提供长期稳定的内核源码、驱动和工具链这比硬件本身更重要。载板是我们自己设计的。核心任务是将RK3568核心板的接口与我们的FPGA模块、AD模块、电源、网络、显示等连接起来。3.2 FPGA模块与AD模块设计FPGA模块我们同样采用了一个现成的、带有PCIe接口的FPGA子板上面包含了FPGA芯片、配置Flash、时钟和电源。这样做可以大幅缩短硬件开发时间。子板通过高速板对板连接器与载板连接连接器上定义了PCIe信号、若干GPIO和电源。AD模块是关键中的关键。我们选择了ADI的AD7606B。这是一款16位、8通道同步采样ADC每通道采样率最高达200KSPS。它支持并行和串行接口我们使用16位并行接口模式将两片AD7606B组合起来实现16通道同步采集。为什么用并行而不是SPI因为16通道100KSPS总数据率是 16通道 * 100K样本/秒 * 2字节/样本 3.2 MB/s。SPI接口在这么高的聚合速率下时序会非常紧张而并行接口可以轻松应对且更易于FPGA进行控制。FPGA与两片AD7606B的连接示意图如下简化FPGA产生一个共用的采样时钟CONVST和读信号RD同时连接到两片ADC。FPGA通过片选CS信号分别选中两片ADC进行读数。16位数据总线DB[15:0]复用FPGA在读取时根据片选区分数据来自哪片ADC的哪个通道AD7606B会在数据线上按顺序输出当前片选下8个通道的数据。3.3 电源与时钟树设计这是容易踩坑的地方。电源RK3568、FPGA、AD7606B对电源噪声都非常敏感。我们采用了多路独立的LDO和DC-DC为模拟部分AD7606B的模拟供电AVcc、数字部分FPGA的Bank供电、RK3568的核电压分别供电并在电源入口和每个芯片的电源引脚附近布置了足够的去耦电容。特别是AD7606B的基准电压源我们使用了高性能的基准芯片并做了精心的滤波和布局以保证ADC的精度。时钟系统的“心跳”。我们为FPGA提供了一颗高精度的有源晶振。FPGA内部使用PLL生成供给AD7606B的采样时钟。供给PCIe硬核的参考时钟100MHz。供给内部逻辑的工作时钟。 确保时钟的纯净和低抖动是保证高速数据采集和传输稳定的基础。时钟线在PCB上要走成差分对如果时钟是差分输出并做好阻抗控制和隔离。实操心得画原理图和PCB时一定要把模拟地AGND和数字地DGND分开处理。我们的做法是在电源入口处通过磁珠或0欧电阻单点连接。AD7606B芯片下方的地平面要完整且属于模拟地区域避免数字信号的噪声通过地平面耦合到敏感的模拟前端。这个细节直接决定了ADC的有效位数ENOB能否达到芯片标称值。4. 软件架构与驱动开发硬件是躯体软件是灵魂。这套方案的软件栈分为三层FPGA逻辑固件、Linux内核驱动、上层应用程序。4.1 FPGA逻辑设计要点FPGA代码使用Verilog或VHDL编写主要模块包括AD7606B控制器一个状态机周期性地产生CONVST脉冲启动所有ADC同步转换然后轮询读取两片ADC的共16个通道数据。读取的数据被存入一个FIFO先入先出存储器。数据打包模块从FIFO中取出数据加上时间戳使用FPGA内部计数器和通道号打包成固定大小的数据帧例如一帧包含1024个采样点*16通道的数据。PCIe DMA引擎这是最复杂的部分。我们使用了FPGA厂商提供的PCIe IP核作为Endpoint。DMA引擎负责在数据包准备好后通过PCIe总线发起一次DMA写操作将数据帧直接写入RK3568内存中预先分配好的缓冲区。同时它会在数据传输完成后向RK3568产生一个MSI中断一种基于消息的PCIe中断。寄存器配置接口FPGA内部实现一组通过PCIe可访问的控制与状态寄存器CSR。RK3568的驱动程序通过读写这些寄存器来配置采样率、启动/停止采集、查询FPGA状态等。// 简化的状态机片段用于控制AD7606B采样序列 always (posedge clk or posedge rst) begin if (rst) begin state IDLE; convst_cnt 0; channel_cnt 0; end else begin case (state) IDLE: if (start_sampling) state ASSERT_CONVST; ASSERT_CONVST: begin convst 1‘b1; if (convst_cnt CONVST_WIDTH) begin convst 1’b0; state CONVERSION_DELAY; convst_cnt 0; end else begin convst_cnt convst_cnt 1; end end CONVERSION_DELAY: // 等待转换完成 READ_CHANNELS: // 循环读取16个通道数据存入FIFO // ... 其他状态 endcase end end4.2 Linux内核驱动开发驱动的作用是让RK3568的Linux系统能识别并控制这个FPGA PCIe设备。主要工作PCIe设备探测在驱动初始化时通过PCIe子系统识别我们的FPGA设备根据Vendor ID和Device ID。探测成功后驱动需要使能设备、申请内存映射I/OMMIO资源从而能访问FPGA内部的配置寄存器。DMA缓冲区分配驱动需要分配一大块连续的物理内存使用dma_alloc_coherent函数作为FPGA DMA写入的目标区域。这块内存的物理地址需要写入到FPGA的DMA目标地址寄存器中。中断处理注册MSI中断处理函数。当FPGA完成一帧数据的DMA传输并触发中断时中断处理函数被调用。它的任务不是处理数据那太耗时而是简单地唤醒一个等待队列或者触发一个工作队列workqueue通知上层有数据就绪。字符设备或sysfs接口驱动通常会创建一个字符设备文件如/dev/fpga_adc或者通过sysfs暴露一些控制节点。这样用户空间的应用程序就可以通过ioctl、read、write等系统调用或者读写sysfs文件来配置采集参数、启动/停止采集、读取数据等。内存映射为了高效传输数据驱动通常会将DMA缓冲区映射到用户空间。应用程序可以直接通过指针访问这段内存避免了数据在用户态和内核态之间的拷贝开销。这是实现高吞吐率的关键。// 驱动中简化的中断处理例程 static irqreturn_t fpga_adc_interrupt(int irq, void *dev_id) { struct fpga_adc_dev *dev dev_id; /* 清除FPGA中断标志位通过写寄存器 */ iowrite32(INTR_CLEAR, dev-reg_base INTR_STATUS_REG); /* 通知数据就绪例如增加环形缓冲区写指针 */ atomic_inc(dev-data_ready); wake_up_interruptible(dev-read_queue); /* 调度底部任务处理数据 */ schedule_work(dev-data_work); return IRQ_HANDLED; }4.3 上层应用程序设计应用层我们使用C和Qt框架开发主要模块数据采集线程通过驱动接口如read或内存映射从内核环形缓冲区中获取数据帧。解析帧头时间戳、通道数将数据按通道分离存入应用层自己维护的数据池中。数据池是一个多通道的环形缓冲区确保新数据不断覆盖旧数据显示线程可以异步读取。波形显示线程使用Qt的QOpenGLWidget进行绘制。为什么用OpenGL因为16通道波形实时刷新对渲染性能要求高。OpenGL可以利用GPU进行硬件加速流畅度远优于纯CPU绘制的QPainter。这个线程定时例如每秒60次从数据池中取出最新的一段数据转换为顶点坐标提交给OpenGL渲染管线进行绘制。支持常见的功能缩放、平移、网格、通道颜色设置、标尺测量等。数据存储线程将采集到的原始数据或预处理后的数据以二进制文件格式如自定义的带时间戳的块结构写入SATA SSD。为了应对高速连续写入文件IO操作需要进行缓冲和优化。网络通信线程可选模块。实现一个TCP服务器将指定的通道数据或处理结果如频谱以固定格式流式发送给远程的上位机软件。配置与管理界面Qt提供的GUI设计器可以快速搭建出专业的配置界面用于设置采样率、量程、通道使能、触发条件、存储路径、网络参数等。整个应用层的架构是典型的生产者-消费者模型多个线程通过锁或无锁环形缓冲区进行数据交换确保UI响应的同时数据采集、处理、存储流水线不间断。5. 系统集成与性能调优硬件和软件模块都准备好后集成和调优才是真正体现功力的地方。5.1 驱动与FPGA的联调这是第一步也是最磨人的一步。工具链是Vivado或国产FPGA厂商的IDE用于FPGA逻辑综合与下载RK3568开发板通过串口和网线连接。PCIe链路训练首先确保FPGA上电后RK3568能通过lspci命令看到这个设备。如果看不到检查PCIe的参考时钟、差分线是否连接正确FPGA的PCIe IP核配置是否正确。寄存器读写测试驱动加载后编写一个简单的小程序通过驱动接口去读写FPGA的配置寄存器。比如写一个值到控制寄存器再读回来验证。这是确认CPU和FPGA之间基本通信正常的关键。DMA与中断测试这是核心。步骤在驱动中分配DMA缓冲区将其物理地址写入FPGA。在驱动中使能FPGA的DMA和中断。通过寄存器命令启动FPGA进行一次单次采集。等待中断发生。中断发生后在中断处理函数中检查DMA缓冲区看里面是否被写入了预期的数据可以预先让FPGA发送一个固定的测试模式比如递增数列。如果数据正确说明从FPGA采集、DMA传输到CPU内存的整个通路是通的。5.2 实时性与延迟优化我们的目标是“实时显示”这意味着从信号被ADC采样到在屏幕上绘制出来这个延迟要尽可能短且稳定。内核优化启用PREEMPT_RT补丁给RK3568的Linux内核打上实时补丁可以显著降低任务调度和中断响应的延迟。这对于保证数据采集线程能被及时唤醒至关重要。CPU隔离与绑核通过内核参数isolcpus将1-2个CPU核心隔离出来专门给我们的数据采集线程和中断处理线程使用。并使用taskset或sched_setaffinity系统调用将相关线程绑定到这些核心上。避免其他系统任务如网络、桌面的干扰。提高时钟精度使用CONFIG_HZ_1000配置将系统时钟频率提高到1000Hz使定时器精度更高。应用层优化内存锁定使用mlockall()锁定采集和显示线程的内存防止其被交换到磁盘造成不可预测的延迟。线程优先级设置数据采集线程为最高实时优先级如SCHED_FIFO优先级99显示线程次之。环形缓冲区设计使用无锁环形缓冲区基于原子操作在不同线程间传递数据避免互斥锁带来的阻塞和优先级反转问题。OpenGL渲染优化使用顶点缓冲对象VBO存储波形数据避免每一帧都从CPU上传数据到GPU。只更新变化的部分。使用双缓冲或三缓冲机制避免画面撕裂。5.3 采样率与带宽的极限测试理论上16通道100KSPS数据率为3.2MB/s。但实际系统能否稳定达到FPGA内部时序在Vivado中必须进行严格的时序约束和时序分析确保在极端温度和电压下FPGA内部逻辑特别是控制ADC和PCIe的部分能稳定运行在目标频率。PCIe带宽测试编写一个FPGA的测试逻辑让它持续以最高速率向RK3568内存发送数据。在RK3568端用驱动和应用统计实际接收到的数据率。我们实测PCIe 2.0 x1的带宽理论约500MB/s单向对于这个应用绰绰有余瓶颈不在这里。系统负载观测在满负荷采集时使用top、htop、perf等工具观察CPU占用率。理想情况下数据采集线程的CPU占用率应该很低因为大部分工作由FPGA的DMA完成了主要负载在显示渲染上。如果CPU占用率过高需要检查驱动或应用层是否有不必要的数据拷贝或低效处理。6. 常见问题与排查实录在实际开发中我们遇到了不少问题这里把典型的几个列出来供大家避坑。问题现象可能原因排查方法与解决方案lspci命令看不到FPGA设备1. PCIe硬件连接问题时钟、差分线。2. FPGA的PCIe IP核未正确配置或加载。3. RK3568的PCIe控制器未使能。1. 用示波器检查PCIe参考时钟100MHz是否正常差分线对间电压差是否正常。2. 检查FPGA逻辑下载是否成功使用FPGA的调试工具如ChipScope/Vivado ILA抓取PCIe IP核的状态信号。3. 检查RK3568内核配置确保PCIe主机控制器驱动已编译并加载dmesgDMA传输数据错乱或中断不触发1. DMA缓冲区物理地址未正确写入FPGA。2. FPGA端的DMA引擎状态机有bug。3. MSI中断未正确配置或路由。1. 在驱动中打印分配的DMA缓冲区物理地址与FPGA寄存器中读取的值对比。2. 在FPGA端用ILA抓取DMA控制信号和数据流看状态跳转和数据打包是否正确。3. 检查/proc/interrupts看MSI中断计数是否增加。检查FPGA和驱动中的MSI配置寄存器。波形显示卡顿、掉帧1. 应用层数据处理或渲染过慢。2. 系统其他任务干扰。3. 数据从驱动到应用层的拷贝开销大。1. 使用性能分析工具如perf定位热点函数。优化OpenGL绘制代码使用VBO。2. 实施CPU隔离和线程绑核提高采集和显示线程的优先级。3. 将驱动中的DMA缓冲区通过mmap映射到用户空间实现零拷贝数据访问。采集到的数据噪声大、精度差1. 模拟前端电路设计问题电源噪声、参考电压不稳。2. 数字信号对模拟部分的干扰。3. ADC采样时钟抖动大。1. 用示波器测量ADC的模拟电源和参考电压看纹波是否在数据手册要求范围内。加强滤波。2. 检查PCB布局确保模拟地和数字地分割正确敏感模拟走线远离数字高速走线。3. 检查FPGA提供给ADC的采样时钟质量尽量使用FPGA的专用时钟输出管脚并做好端接。长时间运行后系统死机或数据出错1. 内存泄漏。2. DMA缓冲区溢出生产速度消费速度。3. 硬件散热问题。1. 使用valgrind检查应用程序确保资源正确释放。2. 在驱动和应用层增加流量控制机制。当应用层处理不过来时通知FPGA暂停采集或丢弃部分旧数据。3. 检查RK3568和FPGA在满载时的温度必要时加装散热片或风扇。一个具体的踩坑案例初期测试时我们发现偶尔会丢失一整帧数据。通过FPGA的ILA抓取信号发现是DMA传输过程中FPGA侧的framing帧间隔偶尔不符合PCIe协议规范导致RK3568的PCIe RC根复合体丢弃了该数据包。根本原因是FPGA内部用于生成PCIe TLP包的状态机在特定时序条件下跳转异常。解决方法是在状态机中增加了更稳健的“等待确认”状态并严格仿真了各种边界情况。这个坑告诉我们对于PCIe、DMA这类高速接口仿真和在线调试必须覆盖到极端情况。7. 方案总结与扩展思考这套基于RK3568FPGA的方案经过几个月的开发和测试最终稳定运行在了客户的产线上。它成功替代了原来那套笨重的工控机商用采集卡组合成本降低了约40%功耗和体积更是大幅减小而性能指标完全满足甚至超过了原有要求。回过头看这个方案的成功有几个关键点一是正确的架构选型让FPGA和ARM各自做最擅长的事二是严谨的硬件设计特别是电源、时钟和地的处理三是深入的软件优化从内核到应用的全栈调优确保了实时性。这个平台还有很大的扩展潜力。例如利用NPURK3568内置的NPU目前闲置。我们可以将采集到的数据如振动信号在本地进行AI推理实现实时的故障预测或异常检测让设备从“数据采集”升级为“智能感知”。更多功能集成FPGA的灵活性允许我们集成更多的工业接口比如直接驱动光耦输入、继电器输出或者实现高速脉冲计数、编码器接口等让这块板子成为一个真正的多功能工业控制器。无线化可以增加4G或5G模块实现数据的无线远程透传适用于分布式或移动式的监测场景。国产化平台正在快速成熟RK3568这样的芯片为我们提供了强大的算力和丰富的生态而FPGA则补足了其在确定性和并行处理上的短板。这种“ARMFPGA”的异构架构在边缘计算和工业物联网领域我觉得会越来越常见。如果你也面临类似的多通道实时采集需求不妨从这个思路入手相信能开辟出一条更优的技术路径。
基于RK3568与FPGA的16通道高速AD采集系统设计与实现
发布时间:2026/5/20 16:03:36
1. 项目概述国产化浪潮下的实时数据采集新选择最近在做一个工业数据采集的项目客户对国产化、实时性和通道数都有硬性要求。传统的方案要么用X86工控机加PCIe采集卡成本高、功耗大要么用一些ARM核心板但多通道同步采集和实时处理能力又成了瓶颈。折腾了一圈最后我们把目光投向了RK3568这颗国产SoC再搭配一颗灵活可编程的FPGA搞出了一套性价比和性能都相当不错的多通道AD实时采集显示方案。今天就把这套方案的思路、踩过的坑和最终实现细节跟大家详细唠唠。简单来说这个方案的核心思想是“软硬协同各司其职”。RK3568作为主控负责运行Linux系统、人机交互界面HMI、网络通信以及复杂的数据分析和存储任务而FPGA则扮演一个高速、精准的“数据搬运工”和“预处理引擎”它直接与多路AD芯片模数转换器对接完成多通道信号的同步采集、数字滤波、初步运算并通过高速接口如PCIe或高速并行总线将规整后的数据高效地传递给RK3568。这样一来既发挥了ARM处理器在应用生态和通用计算上的优势又利用了FPGA在并行处理和实时性上的绝对长处非常适合需要多通道8路、16路甚至更多、高采样率、低延迟的工业现场数据采集与监控场景。如果你正在寻找一个替代传统工控机方案、追求更高集成度和更低成本的实时采集方案或者对信号处理、嵌入式Linux和FPGA协同开发感兴趣那这篇分享应该能给你一些直接的参考。方案里用到的RK3568和国产FPGA现在货源和资料都比以前好了很多自主可控程度高是个值得深入玩一玩的方向。2. 方案核心架构与选型思路为什么是RK3568FPGA这个组合不是凭空想出来的而是基于项目需求一步步推导出来的。我们的核心需求可以概括为至少16通道同步采集、每通道最高100KSPS采样率、实时波形显示、数据本地存储并支持网络上传、整体成本可控、开发周期不能太长。2.1 主控芯片RK3568的考量首先看主控。我们需要一个能跑Linux的处理器因为上层应用如Qt界面、数据库、Web服务在Linux下开发效率最高生态最成熟。但常见的树莓派类芯片接口和可靠性往往难以满足严苛的工业环境。RK3568是瑞芯微推出的一款中高端通用型SoC它的几个特点正好切中我们的需求性能与接口平衡四核Cortex-A55主频最高2.0GHz性能足以流畅运行嵌入式Linux和复杂的图形界面。它集成了丰富的接口双千兆以太网、多个USB、PCIe 2.1、SATA 3.0等为连接FPGA和外设提供了极大灵活性。强大的多媒体与显示能力内置独立的NPU约0.8Tops算力和GPUMali-G52虽然我们这个项目暂时用不到NPU做AI推理但强大的GPU对于多通道波形画面的流畅渲染至关重要。它支持双屏异显方便我们设计一个主显示界面和一个辅助监控界面。国产化与生态RK3568是国内厂商主导设计和推广的芯片供应链相对安全。更重要的是它的Linux内核主线支持度越来越好社区资源和商业SDK都比较丰富能显著降低底层系统移植的难度和风险。注意选择RK3568而不是更便宜的RK3328或RK3399主要是看中了其PCIe接口和更好的长期供货保障。PCIe对于实现与FPGA的高速数据通信目标带宽需达到数百MB/s是关键。2.2 协处理器FPGA的不可或缺性多通道、高实时性的AD采集是纯软件方案哪怕用实时Linux补丁很难完美解决的痛点。主要挑战在于中断延迟Linux系统本身不是硬实时系统即使使用高精度定时器或PREEMPT_RT补丁中断响应和处理仍有微秒级的不确定性对于严格同步的采样时刻控制是个挑战。CPU负载如果由CPU通过SPI或I2C去轮询读取多个AD芯片在高采样率下CPU会被完全拖垮无法进行其他任务。精确时序控制多通道采样需要精确的时钟同步这个用CPU软件时序很难保证。因此引入FPGA成了必然选择。我们选用了一款国产的安路科技的FPGA芯片具体型号根据逻辑规模和接口需求选定。FPGA在这里承担了核心的硬件任务多通道采集控制器FPGA内部实现多个并行的采集控制状态机为每个AD通道产生精确的采样时钟和读取时序确保所有通道在同一时刻被采样实现真正的同步。高速数据接口桥接FPGA一端通过并行总线或SPI接口连接多片AD芯片如ADI的AD7606系列它本身支持8通道同步采样另一端通过PCIe接口与RK3568通信。FPGA内部实现PCIe Endpoint硬核或软核并打包DMA引擎将采集到的数据块直接搬运到RK3568系统内存中无需CPU干预。实时预处理我们甚至在FPGA里加入了简单的预处理逻辑比如数字滤波FIR、量程转换、甚至FFT运算。这样传给RK3568的已经是“半成品”数据进一步减轻了CPU的负担。这种架构下RK3568的CPU只需要在FPGA通过中断告知“数据准备好了”之后去处理内存中已经存在的规整数据包即可采集过程的实时性由FPGA硬件保证软件层的压力大大减轻。2.3 整体数据流设计理解了芯片选型整个方案的数据流就清晰了采集端模拟信号 - 信号调理电路 - 多通道AD芯片 - FPGA同步控制、数据接收、预处理、打包- 通过PCIe DMA - RK3568系统内存的指定缓冲区。处理与显示端RK3568 CPU收到FPGA中断 - 从内存缓冲区读取数据包 - 解包、校验、存入环形缓冲区 - 显示线程从环形缓冲区取数据通过OpenGL或Qt的图形接口进行波形绘制刷新 - 同时存储线程将数据写入本地SSD通过SATA接口网络线程可通过TCP/IP将数据流或处理结果上传至上位机。这个流水线式的设计确保了从采集到显示、存储的各个环节都能高效并发执行。3. 硬件平台设计与关键细节方案定了接下来就是硬件实现。自己画板子固然自由度高但考虑到周期和可靠性我们选择了“核心板载板”的模式。3.1 核心板选型与接口定义我们采购了市面上成熟的RK3568核心板它通常集成了RK3568芯片、LPDDR4内存、eMMC存储和电源管理。选择时重点关注PCIe接口是否引出核心板的板对板连接器必须包含PCIe x1或x2的差分信号线。工业级温度范围项目用于工业现场必须选择支持-40°C ~ 85°C的工业级版本。供应商的Linux BSP支持是否提供长期稳定的内核源码、驱动和工具链这比硬件本身更重要。载板是我们自己设计的。核心任务是将RK3568核心板的接口与我们的FPGA模块、AD模块、电源、网络、显示等连接起来。3.2 FPGA模块与AD模块设计FPGA模块我们同样采用了一个现成的、带有PCIe接口的FPGA子板上面包含了FPGA芯片、配置Flash、时钟和电源。这样做可以大幅缩短硬件开发时间。子板通过高速板对板连接器与载板连接连接器上定义了PCIe信号、若干GPIO和电源。AD模块是关键中的关键。我们选择了ADI的AD7606B。这是一款16位、8通道同步采样ADC每通道采样率最高达200KSPS。它支持并行和串行接口我们使用16位并行接口模式将两片AD7606B组合起来实现16通道同步采集。为什么用并行而不是SPI因为16通道100KSPS总数据率是 16通道 * 100K样本/秒 * 2字节/样本 3.2 MB/s。SPI接口在这么高的聚合速率下时序会非常紧张而并行接口可以轻松应对且更易于FPGA进行控制。FPGA与两片AD7606B的连接示意图如下简化FPGA产生一个共用的采样时钟CONVST和读信号RD同时连接到两片ADC。FPGA通过片选CS信号分别选中两片ADC进行读数。16位数据总线DB[15:0]复用FPGA在读取时根据片选区分数据来自哪片ADC的哪个通道AD7606B会在数据线上按顺序输出当前片选下8个通道的数据。3.3 电源与时钟树设计这是容易踩坑的地方。电源RK3568、FPGA、AD7606B对电源噪声都非常敏感。我们采用了多路独立的LDO和DC-DC为模拟部分AD7606B的模拟供电AVcc、数字部分FPGA的Bank供电、RK3568的核电压分别供电并在电源入口和每个芯片的电源引脚附近布置了足够的去耦电容。特别是AD7606B的基准电压源我们使用了高性能的基准芯片并做了精心的滤波和布局以保证ADC的精度。时钟系统的“心跳”。我们为FPGA提供了一颗高精度的有源晶振。FPGA内部使用PLL生成供给AD7606B的采样时钟。供给PCIe硬核的参考时钟100MHz。供给内部逻辑的工作时钟。 确保时钟的纯净和低抖动是保证高速数据采集和传输稳定的基础。时钟线在PCB上要走成差分对如果时钟是差分输出并做好阻抗控制和隔离。实操心得画原理图和PCB时一定要把模拟地AGND和数字地DGND分开处理。我们的做法是在电源入口处通过磁珠或0欧电阻单点连接。AD7606B芯片下方的地平面要完整且属于模拟地区域避免数字信号的噪声通过地平面耦合到敏感的模拟前端。这个细节直接决定了ADC的有效位数ENOB能否达到芯片标称值。4. 软件架构与驱动开发硬件是躯体软件是灵魂。这套方案的软件栈分为三层FPGA逻辑固件、Linux内核驱动、上层应用程序。4.1 FPGA逻辑设计要点FPGA代码使用Verilog或VHDL编写主要模块包括AD7606B控制器一个状态机周期性地产生CONVST脉冲启动所有ADC同步转换然后轮询读取两片ADC的共16个通道数据。读取的数据被存入一个FIFO先入先出存储器。数据打包模块从FIFO中取出数据加上时间戳使用FPGA内部计数器和通道号打包成固定大小的数据帧例如一帧包含1024个采样点*16通道的数据。PCIe DMA引擎这是最复杂的部分。我们使用了FPGA厂商提供的PCIe IP核作为Endpoint。DMA引擎负责在数据包准备好后通过PCIe总线发起一次DMA写操作将数据帧直接写入RK3568内存中预先分配好的缓冲区。同时它会在数据传输完成后向RK3568产生一个MSI中断一种基于消息的PCIe中断。寄存器配置接口FPGA内部实现一组通过PCIe可访问的控制与状态寄存器CSR。RK3568的驱动程序通过读写这些寄存器来配置采样率、启动/停止采集、查询FPGA状态等。// 简化的状态机片段用于控制AD7606B采样序列 always (posedge clk or posedge rst) begin if (rst) begin state IDLE; convst_cnt 0; channel_cnt 0; end else begin case (state) IDLE: if (start_sampling) state ASSERT_CONVST; ASSERT_CONVST: begin convst 1‘b1; if (convst_cnt CONVST_WIDTH) begin convst 1’b0; state CONVERSION_DELAY; convst_cnt 0; end else begin convst_cnt convst_cnt 1; end end CONVERSION_DELAY: // 等待转换完成 READ_CHANNELS: // 循环读取16个通道数据存入FIFO // ... 其他状态 endcase end end4.2 Linux内核驱动开发驱动的作用是让RK3568的Linux系统能识别并控制这个FPGA PCIe设备。主要工作PCIe设备探测在驱动初始化时通过PCIe子系统识别我们的FPGA设备根据Vendor ID和Device ID。探测成功后驱动需要使能设备、申请内存映射I/OMMIO资源从而能访问FPGA内部的配置寄存器。DMA缓冲区分配驱动需要分配一大块连续的物理内存使用dma_alloc_coherent函数作为FPGA DMA写入的目标区域。这块内存的物理地址需要写入到FPGA的DMA目标地址寄存器中。中断处理注册MSI中断处理函数。当FPGA完成一帧数据的DMA传输并触发中断时中断处理函数被调用。它的任务不是处理数据那太耗时而是简单地唤醒一个等待队列或者触发一个工作队列workqueue通知上层有数据就绪。字符设备或sysfs接口驱动通常会创建一个字符设备文件如/dev/fpga_adc或者通过sysfs暴露一些控制节点。这样用户空间的应用程序就可以通过ioctl、read、write等系统调用或者读写sysfs文件来配置采集参数、启动/停止采集、读取数据等。内存映射为了高效传输数据驱动通常会将DMA缓冲区映射到用户空间。应用程序可以直接通过指针访问这段内存避免了数据在用户态和内核态之间的拷贝开销。这是实现高吞吐率的关键。// 驱动中简化的中断处理例程 static irqreturn_t fpga_adc_interrupt(int irq, void *dev_id) { struct fpga_adc_dev *dev dev_id; /* 清除FPGA中断标志位通过写寄存器 */ iowrite32(INTR_CLEAR, dev-reg_base INTR_STATUS_REG); /* 通知数据就绪例如增加环形缓冲区写指针 */ atomic_inc(dev-data_ready); wake_up_interruptible(dev-read_queue); /* 调度底部任务处理数据 */ schedule_work(dev-data_work); return IRQ_HANDLED; }4.3 上层应用程序设计应用层我们使用C和Qt框架开发主要模块数据采集线程通过驱动接口如read或内存映射从内核环形缓冲区中获取数据帧。解析帧头时间戳、通道数将数据按通道分离存入应用层自己维护的数据池中。数据池是一个多通道的环形缓冲区确保新数据不断覆盖旧数据显示线程可以异步读取。波形显示线程使用Qt的QOpenGLWidget进行绘制。为什么用OpenGL因为16通道波形实时刷新对渲染性能要求高。OpenGL可以利用GPU进行硬件加速流畅度远优于纯CPU绘制的QPainter。这个线程定时例如每秒60次从数据池中取出最新的一段数据转换为顶点坐标提交给OpenGL渲染管线进行绘制。支持常见的功能缩放、平移、网格、通道颜色设置、标尺测量等。数据存储线程将采集到的原始数据或预处理后的数据以二进制文件格式如自定义的带时间戳的块结构写入SATA SSD。为了应对高速连续写入文件IO操作需要进行缓冲和优化。网络通信线程可选模块。实现一个TCP服务器将指定的通道数据或处理结果如频谱以固定格式流式发送给远程的上位机软件。配置与管理界面Qt提供的GUI设计器可以快速搭建出专业的配置界面用于设置采样率、量程、通道使能、触发条件、存储路径、网络参数等。整个应用层的架构是典型的生产者-消费者模型多个线程通过锁或无锁环形缓冲区进行数据交换确保UI响应的同时数据采集、处理、存储流水线不间断。5. 系统集成与性能调优硬件和软件模块都准备好后集成和调优才是真正体现功力的地方。5.1 驱动与FPGA的联调这是第一步也是最磨人的一步。工具链是Vivado或国产FPGA厂商的IDE用于FPGA逻辑综合与下载RK3568开发板通过串口和网线连接。PCIe链路训练首先确保FPGA上电后RK3568能通过lspci命令看到这个设备。如果看不到检查PCIe的参考时钟、差分线是否连接正确FPGA的PCIe IP核配置是否正确。寄存器读写测试驱动加载后编写一个简单的小程序通过驱动接口去读写FPGA的配置寄存器。比如写一个值到控制寄存器再读回来验证。这是确认CPU和FPGA之间基本通信正常的关键。DMA与中断测试这是核心。步骤在驱动中分配DMA缓冲区将其物理地址写入FPGA。在驱动中使能FPGA的DMA和中断。通过寄存器命令启动FPGA进行一次单次采集。等待中断发生。中断发生后在中断处理函数中检查DMA缓冲区看里面是否被写入了预期的数据可以预先让FPGA发送一个固定的测试模式比如递增数列。如果数据正确说明从FPGA采集、DMA传输到CPU内存的整个通路是通的。5.2 实时性与延迟优化我们的目标是“实时显示”这意味着从信号被ADC采样到在屏幕上绘制出来这个延迟要尽可能短且稳定。内核优化启用PREEMPT_RT补丁给RK3568的Linux内核打上实时补丁可以显著降低任务调度和中断响应的延迟。这对于保证数据采集线程能被及时唤醒至关重要。CPU隔离与绑核通过内核参数isolcpus将1-2个CPU核心隔离出来专门给我们的数据采集线程和中断处理线程使用。并使用taskset或sched_setaffinity系统调用将相关线程绑定到这些核心上。避免其他系统任务如网络、桌面的干扰。提高时钟精度使用CONFIG_HZ_1000配置将系统时钟频率提高到1000Hz使定时器精度更高。应用层优化内存锁定使用mlockall()锁定采集和显示线程的内存防止其被交换到磁盘造成不可预测的延迟。线程优先级设置数据采集线程为最高实时优先级如SCHED_FIFO优先级99显示线程次之。环形缓冲区设计使用无锁环形缓冲区基于原子操作在不同线程间传递数据避免互斥锁带来的阻塞和优先级反转问题。OpenGL渲染优化使用顶点缓冲对象VBO存储波形数据避免每一帧都从CPU上传数据到GPU。只更新变化的部分。使用双缓冲或三缓冲机制避免画面撕裂。5.3 采样率与带宽的极限测试理论上16通道100KSPS数据率为3.2MB/s。但实际系统能否稳定达到FPGA内部时序在Vivado中必须进行严格的时序约束和时序分析确保在极端温度和电压下FPGA内部逻辑特别是控制ADC和PCIe的部分能稳定运行在目标频率。PCIe带宽测试编写一个FPGA的测试逻辑让它持续以最高速率向RK3568内存发送数据。在RK3568端用驱动和应用统计实际接收到的数据率。我们实测PCIe 2.0 x1的带宽理论约500MB/s单向对于这个应用绰绰有余瓶颈不在这里。系统负载观测在满负荷采集时使用top、htop、perf等工具观察CPU占用率。理想情况下数据采集线程的CPU占用率应该很低因为大部分工作由FPGA的DMA完成了主要负载在显示渲染上。如果CPU占用率过高需要检查驱动或应用层是否有不必要的数据拷贝或低效处理。6. 常见问题与排查实录在实际开发中我们遇到了不少问题这里把典型的几个列出来供大家避坑。问题现象可能原因排查方法与解决方案lspci命令看不到FPGA设备1. PCIe硬件连接问题时钟、差分线。2. FPGA的PCIe IP核未正确配置或加载。3. RK3568的PCIe控制器未使能。1. 用示波器检查PCIe参考时钟100MHz是否正常差分线对间电压差是否正常。2. 检查FPGA逻辑下载是否成功使用FPGA的调试工具如ChipScope/Vivado ILA抓取PCIe IP核的状态信号。3. 检查RK3568内核配置确保PCIe主机控制器驱动已编译并加载dmesgDMA传输数据错乱或中断不触发1. DMA缓冲区物理地址未正确写入FPGA。2. FPGA端的DMA引擎状态机有bug。3. MSI中断未正确配置或路由。1. 在驱动中打印分配的DMA缓冲区物理地址与FPGA寄存器中读取的值对比。2. 在FPGA端用ILA抓取DMA控制信号和数据流看状态跳转和数据打包是否正确。3. 检查/proc/interrupts看MSI中断计数是否增加。检查FPGA和驱动中的MSI配置寄存器。波形显示卡顿、掉帧1. 应用层数据处理或渲染过慢。2. 系统其他任务干扰。3. 数据从驱动到应用层的拷贝开销大。1. 使用性能分析工具如perf定位热点函数。优化OpenGL绘制代码使用VBO。2. 实施CPU隔离和线程绑核提高采集和显示线程的优先级。3. 将驱动中的DMA缓冲区通过mmap映射到用户空间实现零拷贝数据访问。采集到的数据噪声大、精度差1. 模拟前端电路设计问题电源噪声、参考电压不稳。2. 数字信号对模拟部分的干扰。3. ADC采样时钟抖动大。1. 用示波器测量ADC的模拟电源和参考电压看纹波是否在数据手册要求范围内。加强滤波。2. 检查PCB布局确保模拟地和数字地分割正确敏感模拟走线远离数字高速走线。3. 检查FPGA提供给ADC的采样时钟质量尽量使用FPGA的专用时钟输出管脚并做好端接。长时间运行后系统死机或数据出错1. 内存泄漏。2. DMA缓冲区溢出生产速度消费速度。3. 硬件散热问题。1. 使用valgrind检查应用程序确保资源正确释放。2. 在驱动和应用层增加流量控制机制。当应用层处理不过来时通知FPGA暂停采集或丢弃部分旧数据。3. 检查RK3568和FPGA在满载时的温度必要时加装散热片或风扇。一个具体的踩坑案例初期测试时我们发现偶尔会丢失一整帧数据。通过FPGA的ILA抓取信号发现是DMA传输过程中FPGA侧的framing帧间隔偶尔不符合PCIe协议规范导致RK3568的PCIe RC根复合体丢弃了该数据包。根本原因是FPGA内部用于生成PCIe TLP包的状态机在特定时序条件下跳转异常。解决方法是在状态机中增加了更稳健的“等待确认”状态并严格仿真了各种边界情况。这个坑告诉我们对于PCIe、DMA这类高速接口仿真和在线调试必须覆盖到极端情况。7. 方案总结与扩展思考这套基于RK3568FPGA的方案经过几个月的开发和测试最终稳定运行在了客户的产线上。它成功替代了原来那套笨重的工控机商用采集卡组合成本降低了约40%功耗和体积更是大幅减小而性能指标完全满足甚至超过了原有要求。回过头看这个方案的成功有几个关键点一是正确的架构选型让FPGA和ARM各自做最擅长的事二是严谨的硬件设计特别是电源、时钟和地的处理三是深入的软件优化从内核到应用的全栈调优确保了实时性。这个平台还有很大的扩展潜力。例如利用NPURK3568内置的NPU目前闲置。我们可以将采集到的数据如振动信号在本地进行AI推理实现实时的故障预测或异常检测让设备从“数据采集”升级为“智能感知”。更多功能集成FPGA的灵活性允许我们集成更多的工业接口比如直接驱动光耦输入、继电器输出或者实现高速脉冲计数、编码器接口等让这块板子成为一个真正的多功能工业控制器。无线化可以增加4G或5G模块实现数据的无线远程透传适用于分布式或移动式的监测场景。国产化平台正在快速成熟RK3568这样的芯片为我们提供了强大的算力和丰富的生态而FPGA则补足了其在确定性和并行处理上的短板。这种“ARMFPGA”的异构架构在边缘计算和工业物联网领域我觉得会越来越常见。如果你也面临类似的多通道实时采集需求不妨从这个思路入手相信能开辟出一条更优的技术路径。