我最近正在浏览pi2的GPIO驱动程序,我发现用户空间pi2 GPIO库(如RPi)。GPIO 0.5.11)为BCM2708使用/dev/mem
(从0x20000000开始,GPIO相对从0x200000开始)来映射用户空间内存区域以处理GPIO。但是我发现linux源代码树中的drivers/gpio
被设计为由/sys/class/gpio/*
处理。我没有发现像request_io_region
和__io_remap
这样的I/O端口映射。我的问题是GPIO BCM2708如何映射到内存中?还有别的司机吗?我可以通过R&W到/sys/class/gpio/*
来处理GPIO吗?
我没有发现像request_io_region和__io_remap这样的I/O端口映射。
ARM没有I/O端口空间。所有外设寄存器都被分配到内存空间中的地址。
GPIO如何在内存中映射?
gpio通常被实现为控制寄存器的外设,RPi的BCM2835中的gpio遵循这一约定。这组控制寄存器可以有不同的名称;例如,Atmel将这些寄存器称为并行I/O (PIO)外设。
每个GPIO(或者更准确地说每个引脚)将由每个控制寄存器函数中的一个或多个位表示。控制寄存器功能包括引脚分配(又名多路复用),设置输出为高,设置输出为低,读取引脚电平,电平和边缘检测控制。
现在没有对应于GPIO的单个比特可以读写。对于GPIO,在特定的寄存器中会有一个位来获取输入电平。在另一个寄存器中有一个位将GPIO输出设置为高,在另一个寄存器中有一个位将GPIO输出设置为低。
还有别的司机吗?
是的。pintrl(引脚控制)驱动器比GPIO更底层(即更接近硬件)。这是处理引脚多路复用的pintrl层(即一个引脚是用于外围功能还是作为GPIO)。SoC的pinctrl驱动程序(例如drivers/pinctrl/pinctrl-bcm2835.c
)是您可以找到devm_ioremap_resources()的地方(它反过来调用devm_request_mem_region()和devm_ioremap())用于GPIO寄存器块。
和我可以处理GPIO只是R&W到/sys/class/GPIO/*?
是的。sysfs接口用于访问那些未分配给外设的引脚。
附录
sysfs GPIO接口的功能有限。显然有用户空间库来访问额外的引脚属性(例如启用上拉或下拉电阻),这些属性通常在pinctrl驱动程序的域中。通常,这些库通过/dev/mem psuedo-file直接访问PIO硬件寄存器。请注意,这些技术是不安全的,并且可能会干扰其他设备驱动程序。
这个响应可能不是"on all four ",因为它只是为Raspberry Pi 2提供了一个GPIO基址。
尽管如此,树莓派2上的树莓操作系统提供了一个位于0x3f20,0000
的基址。
$ dmesg -H
[ +0.000749] gpiomem-bcm2835 3f200000.gpiomem: Initialised: Registers at 0x3f200000
一个粗糙的ARMv7 Assembly示例使用上述基址,通过mmmap
调用,在树莓派2上闪烁ACT LED,如下面的链接所示。