如果您认为此问题的构造不正确,请参阅其原始版本。我被要求将这个问题简化为最小的形式。
如果我正在编写Linux设备驱动程序,如何以编程方式访问实际的GPIO引脚?例如:
// Turn a green LED on by sending the GPIO pins 0x11223344
int cmd = encode(Commands.TURN_GREEN_ON);
send_to_gpio_pins(cmd);
同样,如果这一点不清楚,那是因为我试图强迫社区规则保持简单,愚蠢。在这种情况下,请阅读我对这个问题的第一个版本。
答案 0 :(得分:2)
Linux设备驱动程序应该可以访问arch的 gpio 模块提供的一组函数。由于我熟悉Atmel ARM代码并且不确定RPI使用的Broadcom SoC,因此这里有一些真正的 gpio 代码。
ARM SoC上的I / O设备通常是内存映射的(即没有单独的I / O地址空间)。这些物理地址可以映射到内核虚拟地址空间。 (外设寄存器的地址通常由各个设备驱动程序映射,供其专用。)
一旦映射到虚拟存储器,包含或控制GPIO引脚状态的寄存器就可以通过普通的读或写存储器操作进行访问(符合C语言要求)。有关这些器件寄存器中每个位的确切分配/功能,请参考Broadcom SoC hardware document。
在将GPIO用作输入引脚或输出引脚之前,必须配置GPIO引脚。通常,引脚将具有多种用途(它是“多路复用的”),因此必须在早期板初始化期间选择其中一个特定功能。通过写入设备配置寄存器(映射到存储器位置)来执行这些分配。
Atmel函数用于写入GPIO引脚的值(来自arch/arm/mach-at91/gpio.c):
/*
* assuming the pin is muxed as a gpio output, set its value.
*/
int at91_set_gpio_value(unsigned pin, int value)
{
void __iomem *pio = pin_to_controller(pin);
unsigned mask = pin_to_mask(pin);
if (!pio)
return -EINVAL;
__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
return 0;
}
EXPORT_SYMBOL(at91_set_gpio_value);
用于读取GPIO引脚值的Atmel函数:
/*
* read the pin's value (works even if it's not muxed as a gpio).
*/
int at91_get_gpio_value(unsigned pin)
{
void __iomem *pio = pin_to_controller(pin);
unsigned mask = pin_to_mask(pin);
u32 pdsr;
if (!pio)
return -EINVAL;
pdsr = __raw_readl(pio + PIO_PDSR);
return (pdsr & mask) != 0;
}
EXPORT_SYMBOL(at91_get_gpio_value);
希望你可以在你使用的内核中找到类似的代码(例如 grep “{gpio”的System.map
符号文件)。