Userspace I/O

UIO

概念

对于很多类型的设备,为它创建一个linux驱动有点过头。其实真正需要的只是得到处理其中断的一种方式还有访问其设备内存空间的权限。而真正控制设备的逻辑其实并没有必要搞到内核里面去,因为这种设备并不需要用到内核提供的其它资源。类似这种设备的就比如 industrial I/O cards。
UIO就用来解决这个问题,全称:userspace I/O system。对于典型的industrial I/O cards,驱动只需要很少的一点内核模块,而大部分都在用户空间执行。这能简化开发,而且减少了内核模块发生严重bug的可能。
那哪些设备适合用uio来驱动呢?

  • 能通过写它的内存空间完全控制这个设备
  • 设备能产生中断
  • 不适合已有的标准内核子系统(既然有标准的一套可以支持,就不需要uio了)

uio的机制

uio这套框架抽象出一个uio设备,在/dev/uioX,X表示标号,如/dev/uio0。另外在sysfs中有一些属性用来访问uio设备的信息,处于/sys/class/uio/uioX。

/dev/uioX

/dev/uioX 用来访问设备的地址空间 —— 使用mmap操作
当通过read函数来读它的时候,会阻塞,直到中断来临才返回,所以可以通过读它来处理中断。当然,也可以通过select操作来等待中断。read函数返回后,读到的值代表到目前为止所有的中断数 —— 这可用来检查是否遗漏了中断。
对于某些硬件设备来说,内部可能有好几个中断源,但同时却没有分开的中断mask和状态寄存器,这时如果中断处理函数是通过写硬件设备的寄存器来disable这个中断,那么用户空间就不知道到底来的是哪个中断。这样,kernel就必须彻底disable掉这个中断,这样就可以不操作这个硬件设备。如此一来,用户空间就能辨认出中断是谁产生的,可是这样就不能再次enable这个中断了。另外,还有一个边缘场景:硬件设备的中断状态和确认寄存器是一起的(combined),而且re-enable中断是个读-修改-写入的操作,如果与此同时一个新的中断又发生了就会造成竞争。为了解决这个问题,UIO框架实现了对/dev/uioX的write 操作。如果不存在上述问题,那么这个操作可以被忽略(不用使用);否则,write操作用来enable或disable这个设备的中断。它内部会调用到irqcontrol(),如果没有实现irqcontrol(), write操作会返回错误码:-ENOSYS。
为了合理地处理中断,你自己定制的kernel模块可以提供它自己的中断handler,这个会被自动调用。
对于那些不能产生中断而是通过polling寄存器方式的硬件设备,可以通过设置一个接受可配置时间间隔的timer来触发中断。通过在timer的event handler中调用uio_event_notify()来模拟这个中断。

/sys/class/uio/uioX

这个目录下面会有哪些文件呢?

  • name
    设备名,建议用模块的名字

  • version
    驱动版本

  • event
    自上次这个节点被访问以来这个驱动处理的中断的次数

  • maps/mapX
    内存映射属性目录
    对于采用内存映射方式嵌入系统的设备,是通过mmap来完成映射访问,就会有这个属性。而且创建了多少组的内存映射,就会有多少组mapX, X=0,1,…,N-1。每组mapX都会有如下4个只读属性

    • name
      名字
    • size
      大小
    • addr
      基地址
    • offset
      偏移量
      size、addr、offset的单位都是字节
  • portio/portX
    某些体系架构支持非内存映射IO, 例如x86架构,那么当设备使用的是端口映射IO的方式嵌入系统的时候,就用的是portio。而且有多少组port就会有多少组portX, X=0,1,…N-1。每个portX下就会有如下只读属性

    • name
      名字
    • start
      起始port
    • size
      port的个数
    • porttype
      port的类型

用户态编程注意事项

用户态首先需要得到/sys/class/uio/uioX/maps/mapN/size的大小
然后根据需要打开/dev/uioX(c::open())。
再使用mmap来做映射:
mmap的原型:
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
start填NULL, length应该填sysfs中uioX对应的mapN的size, offset是重点,其值应该是N*getpagesize(),对应mapN
然后就可以直接读写mmap返回的指针指向的空间了。

好的,关于PetaLinux开发UIO驱动,我可以给你一些基本的指导。 首先,UIO是一种通用的用户空间I/O框架,它允许用户空间的应用程序访问设备驱动程序。在PetaLinux中,你可以使用UIO驱动程序来访问PL中的IP核。下面是一些基本的步骤: 1.首先,在PetaLinux中启用UIO支持。你可以使用petalinux-config命令来打开配置菜单,选择Kernel菜单,然后选择Device Drivers -> Userspace I/O driver support -> Userspace I/O platform driver with generic IRQ handling支持。 2.然后,编你的UIO驱动程序。你需要创建一个新的内核模块,实现UIO驱动程序的基本功能。你需要实现的主要函数是probe和remove,它们分别在设备被识别和移除时调用。在probe函数中,你需要初始化设备并注册UIO设备,然后将设备映射到用户空间。在remove函数中,你需要取消设备的映射和UIO设备的注册。 3.编译并加载你的UIO驱动程序。在PetaLinux中,你可以使用petalinux-build命令来编译内核模块,并使用petalinux-module命令将其加载到系统中。 4.在用户空间中使用UIO设备。一旦你的UIO驱动程序加载到系统中,你就可以在用户空间中使用它了。你需要使用mmap函数将UIO设备映射到用户空间,并使用read和write函数访问设备。 希望这些基本的指导对你有所帮助。如果你需要更详细的指导,可以参考PetaLinux文档或者一些UIO驱动程序的示例代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值