1

如果您认为这个问题的构造不正确,请查看其原始版本。我被要求将这个问题简化为最小形式。

如果我正在编写 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);

同样,如果这不清楚,那是因为我试图遵守社区规则以使其保持简单、愚蠢。在这种情况下,请阅读我的这个问题的第一个版本。

4

1 回答 1

2

Linux 设备驱动程序应该可以访问 arch 的gpio模块提供的一组功能。由于我熟悉 Atmel ARM 代码并且不确定 RPI 使用的 Broadcom SoC,这里有一些真正的gpio代码。

ARM SoC 上的 I/O 设备通常是内存映射的(即没有单独的 I/O 地址空间)。这些物理地址可以映射到内核虚拟地址空间。(外设寄存器的地址通常由单独的设备驱动程序映射以供其专用。)
一旦映射到虚拟内存中,包含或控制 GPIO 引脚状态的寄存器可以通过普通的读取或写入内存操作简单地访问(同时符合 C 语言要求)。有关这些设备寄存器中每个位的确切分配/功能,请参阅Broadcom SoC 硬件文档

在将 GPIO 用作输入引脚或输出引脚之前,必须配置 GPIO 引脚。引脚通常有多种用途(它是“多路复用的”),因此必须在早期电路板初始化期间选择其中一种特定功能。这些分配是通过写入设备配置寄存器(映射到内存位置)来执行的。

用于写入 GPIO 引脚值的 Atmel 函数(来自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符号System.map文件以获得“gpio”)。

于 2012-12-08T21:58:05.933 回答