基于 Linux UIO 的高效 ARM-FPGA 通信中断处理方案

作者
Martin Feng
文章來源
Cytech Engineer

基于 Linux UIO 的高效 ARM-FPGA 通信中断处理方案

应用背景

在 ARM 和 FPGA 之间通信的通信过程中,通信开始或者完成时,需要实时通知对方,如果 ARM 使用类似 while (1) 循环进行反复查看标志位,会造成 CPU 空转,影响工作效率。如果使用中断加内核驱动的方式,虽然可以提高效率,但这对开发驱动的工程师有较高的技术要求,因为内核驱动运行在内核态,一旦出现错误,可能会造成整个内核的崩溃,因此需要一种既高效又不依赖复杂内核驱动的解决方案。

UIO 简介

UIO (Userspace I/O) 是运行在用户空间的 I/O 技术,Linux 系统中一般的驱动设备都是运行在内核空间,应用程序在用户空间调用即可。UIO 则是将驱动的小部分运行在内核空间,在用户空间实现驱动的绝大多数功能,使用 UIO 可以避免设备的驱动程序需要随着内核的更新而更新的问题。

相比传统内核态驱动,UIO 的优势包括:

  • 简化了驱动开发流程,降低了内核崩溃的风险
  • 避免了因内核版本更新而需要同步更新驱动的问题
  • 支持用户空间直接访问硬件,提高开发灵活性和效率

图1 UIO 驱动的内核部分、用户空间部分和 UIO 框架以及内核的关系
图1 UIO 驱动的内核部分、用户空间部分和 UIO 框架以及内核的关系

实现方案及步骤

配置内核设备树

首先对设备树节点进行修改,将设备的 compatible 属性设置为 generic-uio,以加载通用 UIO 驱动,如下图 (图2) 所示:

图2 将设备的 compatible 属性设置为 generic-uio
图2 将设备的 compatible 属性设置为 generic-uio

配置内核

Linux 内核中已有 UIO 驱动,但是我们需要使能,才能在内核启动。根据内核设备树,加载相应的驱动。具体的内核增加的配置,参考下图 (图3):

图3 增加的内核驱动配置
图3 增加的内核驱动配置

应用层使用

下图 (图4) 为大家提供一套相对完整的参考代码:

图4 应用层使用参考代码
图4 应用层使用参考代码

说明

在步骤 3 中,read 为阻塞读。设备没有读到数值,该线程进入阻塞态。待时机合适,立马进入运行态。在进入阻塞态,释放处理器的占用。待有数值以后,处理器立马进入运行态,如此即可高效完成工作任务。

UIO 框架说明

Linux UIO 框架的代码位于内核源码 drivers/uio/uio.c。Linux UIO 框架也会调用内核提供的其他 API 接口函数。通过一个设备文件和几个 sysfs 属性文件访问 UIO 设备。第一个设备的设备文件被称为 /dev/uio0,后续的设备被称为 /dev/uio1、/dev/uio2 等。

中断是通过读取 /dev/uioX 来处理的。一旦中断发生,来自 /dev/uioX 的 blocking read () 将立即返回。除此以外,也可以在 /dev/uioX 上使用 select() 来等待中断。从 /dev/uioX 读取的整数值表示总的中断数,可以使用这个数来计算是否错过了一些中断。

优势与总结

使用 UIO 框架实现 ARM 和 FPGA 的高效通信,不仅减少了 CPU 的资源占用,还降低了开发门槛,提升了系统稳定性。通过用户空间完成大部分驱动逻辑,既实现了高效中断处理,又简化了驱动维护,是一种高效可靠的通信方案。

本文主要介绍如何通过 UIO 技术,在 ARM 与 FPGA 通信中利用用户态实现高效中断处理,避免内核驱动的复杂性和风险。欲了解更多 Altera 相关方案或技术信息,可点击下方「联系我们」,提交您的需求,澳门人巴黎人1797公司愿意为您提供更详细的技术解答。

 

更多資訊: