如何使设备驱动程序与硬件通信?

如何使设备驱动程序与硬件通信?

在此输入图像描述

我已经准备好用户空间应用程序,设备文件 mknoded,设备驱动程序已插入内核,并且有带有 UART 协议的设备。我试图找出设备驱动程序(它具有硬件的基址和 IRQ 线号)和硬件之间发生的情况。当用户空间应用程序提出请求时,具有硬件基地址的设备驱动程序将处理它,并且当硬件想要提出请求时,它会激活 IRQ 线。

问题:

  1. 我需要像在 8051 微控制器中那样将代码转储到某个地方吗?
  2. 我应该什么时候打开设备?

我错过了流量。

答案1

PCI/PCIe总线具有硬件自动配置功能,因此Linux内核包含一个PCI总线驱动程序,可以读取所有PCI/PCIe设备的硬件ID。通过lspci -nn,您可以自己查看这些 ID。

如果此时还没有为硬件加载驱动程序,内核将生成驱动程序模块加载请求,相当于:

modprobe pci:v0000<PCI vendor ID>d000<PCI device ID>sv<subvendor ID>sd<subdevice ID>bc<base class ID>sc<subclass ID>i<programming interface ID>

驱动模块应该包括相应的 情态信息,用于modprobe查找匹配模块。如果运行modprobe -c | grep pci:,您将看到所有当前安装的驱动程序模块的 modalias 行。

加载驱动程序后(和/或如果有任何内核级 PCI(e) 热插拔事件,在支持热插拔的硬件中),驱动程序将查找驱动程序了解的硬件。如果驱动程序找到可以运行的设备,通常会触发 udev 热插拔事件来自动创建必要的设备文件。

如果默认值不适合您的用例,您可以使用 udev 规则修改设备文件的路径、名称、所有权和权限,和/或运行任意脚本操作。在大多数情况下,手动mknod应该是不必要的,并且由于 Linux 自内核版本 2.6 以来一直使用非持久性/dev设备文件系统,因此任何手动命令的效果mknod都将在下次重新启动时丢失。

司机可能一旦检测到设备,就采取进一步的步骤来询问/初始化设备,或者驱动程序可以简单地设置与设备节点相对应的内核端基础设施并等待来自用户空间的输入。

如果驱动程序没有找到任何相关硬件,它将保持加载在内存中,等待内核级热插拔事件,这些事件可能会告诉它再次寻找设备。

但 PCI(e) UART 卡很可能会被检测为只是一个串行端口设备(即设备/dev/ttyS*)。由于串行端口技术非常古老,因此没有可靠的方法可以探测串行端口以识别连接到端口的内容;有一些检测方案,但在 Linux 中,这些通常在用户空间中实现,例如gpsdGPS 接收器设备和ModemManager3G/4G 无线调制解调器。这些服务将查找串行端口,检查端口握手线的状态,如果看起来有连接(即串行端口的传入 DSR 线处于活动状态),它们将查找传入数据和/或发送一些标准查询字符串。

例如,ModemManager 可能会发送AT到一个新的串行端口:如果设备响应OK,则另一端的设备似乎能够理解经典的 Hayes AT 命令,因此它可能是某种调制解调器;然后ModemManager将发送进一步的命令以更准确地识别它。

这种主动探测很可能会干扰 UART 设备的某些使用。如有必要,您可以使用 udev 规则告诉 ModemManager 它应该完全忽略特定的 UART 设备。

例如,我有一个带有 PCIe 串口卡的系统:

# lspci -nn
...
04:00.0 Serial controller [0700]: Oxford Semiconductor Ltd OXPCIe952 Dual 16C950 UART [1415:c158]
...

它有两个端口,udevadm info -q all -a -n /dev/ttyS<number>在我的所有/dev/ttyS*设备上运行可以让我识别它们。第一个端口具有 udev 属性ATTR{line}=="1",第二个端口具有ATTR{line}=="2".

我现在可以将我的特殊串行设备连接到该卡的端口 #1,并将这样的 udev 规则写入文件中/etc/udev/rules.d/99-my-uart-device.rules

SUBSYSTEM=="tty", DRIVERS=="serial", ATTRS{vendor}=="0x1415", ATTRS{device}=="0xc158", ATTRS{line}=="1", ALIAS="my_serial_device", ENV{ID_MM_DEVICE_IGNORE}="1"

此规则将导致创建一个别名(符号链接),/dev/my_serial_device以始终引用该串行端口卡的端口 #1,无论可能向系统添加什么其他类似 UART 的设备以及检测到它们的顺序如何它还会告诉ModemManager不要探测这个端口(该ENV{ID_MM_DEVICE_IGNORE}="1"部分)。

我现在可以设置一个应用程序来代替/dev/my_serial_device例如,/dev/ttyS1并相信它将始终使用正确的物理串行端口与设备进行通信。

串口卡由 PCIe 插槽供电,因此它会始终与计算机一起通电并被检测到。连接到端口的设备可以保持断电状态,直到启动使用该设备的应用程序之前。

相关内容