基于Linux+FPGA的嵌入式异构系统搭建:软硬件协同开发的完整流程
在Zynq、ZU+等SoC FPGA平台上,ARM处理器系统(PS)与可编程逻辑(PL)通过AXI总线紧耦合,让"Linux跑应用+FPGA做加速"成为嵌入式异构计算的主流范式。两者分工清晰:PS负责网络协议、文件系统、人机界面等复杂控制;PL承担高速数据采集、硬件加速算法、纳秒级实时响应。本文梳理从任务划分到系统固化的软硬件协同开发完整流程。
第一步:系统架构与任务划分
项目启动阶段,系统架构师、FPGA工程师、嵌入式软件工程师必须共同定义软硬件接口这一"核心契约":
PS端(Cortex-A9/A53):网络通信、GUI、复杂业务逻辑、文件系统
PL端(FPGA逻辑):高速ADC/DAC采集、图像并行处理、定制协议、实时控制
接口定义:低速控制用AXI-Lite总线访问寄存器;高速大数据量传输用AXI-Stream结合DMA,通过AXI-HP接口直接读写DDR内存;中断分配明确PL抛给PS的硬件中断号
第二步:Vivado硬件平台构建
在Vivado中搭建Block Design:
# 创建Zynq处理系统并自动连线
create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 ps7_0
apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 \
-config {make_external "FIXED_IO, DDR"} [get_bd_cells ps7_0]
随后添加自定义IP或Xilinx IP库(AXI GPIO、AXI DMA、FIFO等),用AXI Interconnect将它们连接到PS的AXI端口。AXI接口选型有讲究:
GP接口:32/64位,适合控制寄存器访问,时钟100-250MHz
HP接口:64位、带FIFO缓冲,适合DMA大数据传输
ACP接口:保持缓存一致性,适合频繁访问的小数据量
配置完成后生成比特流,并导出硬件描述文件(.xsa)——这是交付给软件开发端的"硬件契约"。
第三步:PetaLinux构建Linux系统
基于XSA文件创建PetaLinux工程:
petalinux-create -t project --name my_project
cd my_project
petalinux-config --get-hw-description=../vivado/system.xsa
petalinux-config -c kernel # 启用Xilinx DMA驱动
petalinux-config -c device-tree # 修改设备树
petalinux-build
构建产物包含:
BOOT.BIN:含FSBL、bitstream、U-Boot
image.ub:Linux内核镜像
rootfs.cpio.gz:根文件系统
第四步:PS与PL的两种通信模式
模式一:AXI-Lite低速控制 + UIO用户态访问
对于只需读写控制寄存器、启停硬件模块的场景,用UIO(Userspace I/O)框架将FPGA外设暴露给用户态,无需编写内核驱动:
myip: myip@40000000 {
compatible = "generic-uio";
reg = <0x40000000 0x10000>;
interrupts = <0 29 4>;
};
用户态程序通过mmap直接操作寄存器:
int fd = open("/dev/uio0", O_RDWR);
volatile uint32_t* regs = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
regs[0x010/4] = 1; // 写CTRL.start
uint32_t count;
read(fd, &count, 4); // 阻塞等待中断
uint32_t status = regs[0x014/4];
regs[0x018/4] = 1; // 写1清中断
模式二:AXI DMA高速数据传输
当PL端产生持续高速数据流(如ADC采样、图像采集)时,必须启用AXI DMA。典型数据通路:
PL数据源 → AXI4-Stream → AXI_DMA → AXI_HP → DDR内存 → Linux应用
在Vivado中为DMA预留物理内存,避免Linux内核分配不可预测的缓冲区:
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
dma_reserved: buffer@10000000 {
reg = <0x10000000 0x1000000>; // 16MB预留
};
};
Linux应用通过mmap映射这块"专属火车站",再用UIO控制DMA寄存器发起传输:
// 数据通路:mmap预留内存 → UIO触发DMA → 等待中断
void* dma_buf = mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE,
MAP_SHARED, mem_fd, 0x10000000);
// 通过UIO写DMA寄存器,启动S2MM通道
// 等待DMA完成中断
read(uio_fd, &count, 4);
// 直接处理dma_buf中的数据
DMA的S2MM通道将PL的AXI4-Stream数据写入DDR,MM2S通道从DDR读取数据发往PL,两通道独立可形成全双工。
第五步:联合调试与固化
联合调试是异构系统最具挑战的环节——Vivado的ILA(集成逻辑分析仪)抓取PL内部信号,Vitis调试器单步执行PS端C代码,两边必须同时观测才能定位问题。
调试完成后,将BOOT.BIN、image.ub、rootfs.cpio.gz打包烧录至SD卡或QSPI Flash,上电启动。
写在最后
Linux+FPGA异构系统的软硬件协同开发,本质是"分工上相互独立,接口上强耦合"。Vivado负责PL硬件平台构建并导出XSA,PetaLinux基于XSA构建设备树和内核,UIO让用户态程序快速访问寄存器,AXI DMA实现高速数据零拷贝搬运。掌握这条"Vivado → XSA → PetaLinux → UIO/DMA → 应用联调"的工具链,你就拥有了在Zynq平台上融合Linux生态与FPGA并行算力的完整能力。当你的下一个项目既需要Linux的网络通信能力,又需要FPGA的硬件加速时,异构协同是唯一正确答案。





