C 设备驱动程序:如何获得对实际引脚/硬件的编程访问?

C 设备驱动程序:如何获得对实际引脚/硬件的编程访问?,c,linux-device-driver,raspberry-pi,gpio,C,Linux Device Driver,Raspberry Pi,Gpio,如果你认为这个问题的结构不正确,请查看其原始版本。我被要求把这个问题简化为最简单的形式 如果我正在编写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); 再说一次,如果这还不清楚的话,那是因为我试图遵守社区规则,让它简单、愚蠢。在这

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

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

再说一次,如果这还不清楚的话,那是因为我试图遵守社区规则,让它简单、愚蠢。在这种情况下,请阅读我的第一个问题版本。

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

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

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

用于写入GPIO引脚值的Atmel函数(从):

读取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的符号文件)。

除了主要问题之外,我已经控制了编辑所有内容的冲动。相反,你应该考虑自己做这件事。另外,考虑将标题改为问题。Nocturno,希望编辑读得更好,尽管我担心现在我要回答很多“需要更多信息”的后续问题/评论。这是一个折衷方案……IMO使用GPIO在两个计算机系统之间进行通信是个坏主意。您正试图在不评估协议要求的情况下立即实现某些内容。这应该是主从连接吗?你需要定义这些基本假设。您构建的任何接口都是处理器对处理器的接口;您无法远程控制其他设备的GPIO。为了控制用户对本地GPIO的访问,有些人使用sysfs而不是设备驱动程序。@HeineyBehinds好多了,谢谢。很有趣。为了“保持简单”,这个问题现在演变成了XY问题(尽管这个修订的问题确实有优点,因为它是可以回答的)。
/*
 * 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);