GPIO是如何映射到内存中的?

How GPIO is mapped in memory?

我最近浏览了 pi2 的 GPIO driver,我发现用户 space pi2 GPIO lib(比如 python 的 RPi.GPIO 0.5.11)使用 /dev/mem 对于 BCM2708(从 0x20000000 开始,GPIO 相对从 0x200000 开始)映射用户 space 内存区域以处理 GPIO。但是我发现 linux 中的 drivers/gpio 源代码树被设计为由 /sys/class/gpio/* 处理。我没有发现 I/O 端口映射,如 request_io_region__io_remap。 我的问题是 BCM2708 的 GPIO 如何映射到内存中?还有另一个driver吗?我可以通过 R&W 处理 GPIO 到 /sys/class/gpio/* 吗?

I found nothing like I/O ports mapping like request_io_region and __io_remap.

ARM 没有 I/O 端口 space。所有外围寄存器都分配给内存中的地址 space.

How GPIO for BCM2708 mapped in memory ?

GPIO通常作为控制寄存器的外设实现,树莓派BCM2835中的GPIO遵循这一约定。这组控制寄存器可能有不同的名称;例如 Atmel 将这些寄存器称为并行 I/O (PIO) 外设。

每个 GPIO(或更准确地说每个引脚)将由每个控制寄存器函数中的一个或多个位表示。控制寄存器功能包括引脚分配(又称多路复用)、将输出设置为高电平、将输出设置为低电平、读取引脚电平以及电平和边沿检测控制。

IOW 没有可以读取和写入对应于GPIO 的单个位。对于 GPIO,特定寄存器中会有一个位来获取输入电平。另一个寄存器中有一个位用于将 GPIO 输出设置为高电平,另一个寄存器中有一个位用于将 GPIO 输出设置为低电平。

Is there another driver?

是的。 pinctrl(引脚控制)驱动程序是比 GPIO 更底层(即更接近硬件)的驱动程序。它是处理引脚复用的 pinctrl 层(即一个引脚是用于外围功能还是用作 GPIO)。
SoC 的 pinctrl 驱动程序(例如 drivers/pinctrl/pinctrl-bcm2835.c)是您可以找到 devm_ioremap_resources()(进而调用 devm_request_mem_region()devm_ioremap()) 用于 GPIO 寄存器块。

And can I handle GPIO just by R&W to /sys/class/gpio/*?

是的。 sysfs 接口用于访问那些未分配给外围设备的引脚。

附录
sysfs GPIO 接口的功能有限。
显然有 userspace 库可以访问通常在 pinctrl 驱动程序域中的其他引脚属性(例如启用上拉或下拉电阻)。通常,此类库通过 /dev/mem 伪文件直接访问 PIO 硬件寄存器。请注意,此类技术并不安全,并且可能会干扰其他设备驱动程序。

此响应可能不是 "on all fours",因为它只是为 Raspberry Pi 2 提供了一个 GPIO 基地址。

尽管如此,Raspberry Pi 2 上的 Raspbian OS 提供了位于 0x3f20,0000 的基地址。

$ dmesg -H 
[  +0.000749] gpiomem-bcm2835 3f200000.gpiomem: Initialised: Registers at 0x3f200000

使用上述基地址的原始 ARMv7 汇编示例,通过 mmmap 调用 blink Raspberry Pi 2 上的 ACT LED 在 [=26 中指示=] 下面。

https://github.com/InfinitelyManic/Raspberry-Pi-2