访问设备驱动程序中 Linux 硬件的引脚

Accessing pins of Linux hardware inside device driver

我阅读了 this excellent DIY article 关于编写 Linux 设备驱动程序的内容,但我仍然没有在此处的主要项目上看到 "forest through the trees"。最终,最终用户软件(在用户 space 中)需要与硬件通信(设备驱动程序正在 驱动 /wrapping/adapting)。硬件由电力驱动,因此需要将软件命令转换为 hi/lo 信号(1 和 0),这些信号被推送到电路和连接的硬件中。一个愚蠢的简单例子:

# Send a connected LED device a command to turn on at the software layer:
led.turnOn();

# In the device driver, somehow, translate this to 0x01 (1, or 00000001):
void turnOn() {
    int signal = 1;

    # Now, *somehow*, push this to the hardware with the following pinout (see below):
}

# Pinout
0   ---------------->  /----------\
0   ---------------->  |          |
0   ---------------->  |          |
0   ---------------->  | Hardware |
0   ---------------->  |          |
0   ---------------->  |          |
0   ---------------->  |          |
1   ---------------->  \----------/

我没有看到的是:在设备驱动程序 C 代码中,我如何 read/write bytes/data 和来自底层硬件设备?

我能看到的唯一理论是,也许,因为 Linux 设备被用户 space 视为 "files" (dev/led),也许正在写入数据,例如 0x01,to dev/led 是我们向连接的设备发送命令的方式;也许从设备读取数据就是我们从设备读取数据的方式。

我是在朝着正确的方向前进,还是偏离了轨道?

这实际上取决于设备的性质以及它与系统的连接方式 - 它可以是内存映射的,或者映射到某种可寻址的 I/O space,或者例如,PCI-e 或 USB 等总线。重点是在驱动程序中对此进行抽象,以便程序员不必关心低级细节。

例如,对于 PCI 设备,板可能会映射到一个物理地址范围。在此范围内,您可以访问某些寄存器来控制硬件。假设您有一个简单的 I/O 卡,带有一个 32 位寄存器,并且该卡映射到物理地址 0xf0000000。该寄存器用于控制32个LED输出,你想点亮LED 0:

volatile uint32_t * const my_card_register = (uint32_t *) 0xf0000000;
                                      // address of PCI card register
*my_card_register |= 0x00000001;      // set bit 0 in register to turn on LED