我是编写设备驱动程序的新手。
我想为 ARM 平台上的外围设备编写设备驱动程序。
第一个问题:在 ARM 平台上为外设编写设备驱动程序与在 Linux 中的 x86 上编写设备驱动程序有什么不同?
第二个问题:我检查了 /proc/iomem 文件以查看处理器的当前地址映射。但是,并非所有外围设备(包括我要访问的外围设备)都不存在于该文件中。如何包含外围设备的地址范围?
第三个问题:设备树在编写设备驱动程序中的重要性是什么?
我是编写设备驱动程序的新手。
我想为 ARM 平台上的外围设备编写设备驱动程序。
第一个问题:在 ARM 平台上为外设编写设备驱动程序与在 Linux 中的 x86 上编写设备驱动程序有什么不同?
第二个问题:我检查了 /proc/iomem 文件以查看处理器的当前地址映射。但是,并非所有外围设备(包括我要访问的外围设备)都不存在于该文件中。如何包含外围设备的地址范围?
第三个问题:设备树在编写设备驱动程序中的重要性是什么?
如果驱动程序不存在于内核源代码树中,并且设备是在设备地址空间中映射的内存,则必须在某处声明设备资源(地址区域、中断行)。在旧版本的内核中,这是板文件的职责,但现在它已移至设备树。
所以 x86 架构的主要区别不是你如何编写驱动程序,而是你如何匹配设备和驱动程序。在 x86 上,您有例如 pci 驱动程序和可发现的 pci 设备。在 ARM 上,通常没有这样的自描述硬件,为了模拟整个设备/驱动程序的舞蹈,创建了平台总线。
所以ARM上典型的设备驱动就是平台驱动,关联的设备就是平台设备。当前内核中的以太网 mac 驱动程序示例在这里。
在上面链接的驱动程序中,驱动程序代码不知道设备所在的位置。此信息在探测时使用platform_device
对象传递给驱动程序。平台设备可以这样描述(来源):
static struct platform_device at91sam9260_eth_device = {
.name = "macb",
.id = -1,
.dev = {
.dma_mask = ð_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = ð_data,
},
.resource = eth_resources,
.num_resources = ARRAY_SIZE(eth_resources),
};
平台设备可以从这里显示的 c 代码创建,也可以在设备树中描述。在这两种情况下,在驱动程序探测到设备之前,您都不会在 proc/iomem 中看到任何内容。这与大多数设备是 PCI 设备的 x86 世界形成鲜明对比。
这是相同的设备,但在设备树文件中进行了描述:
macb0: ethernet@fffc4000 {
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xfffc4000 0x100>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb_rmii>;
status = "disabled";
};
1.只要外设接口与SoC类似(即在两个平台上使用相同的硬件接口),相同的驱动程序可以在x86和ARM上使用。这是开发独立于 Linux 内核核心的模块化驱动程序的优势。
2.如果当前地址映射()中不存在您的特定外围设备,/proc/iomem
则可能意味着以下两种可能性之一:
有关外围设备的任何其他信息?它是如何连接到 SoC 的?
3. Linux 内核中的设备树用于描述众多硬件(片上和外围设备)、它们的互连性以及适用于它们在特定平台/板上进行正确配置和初始化的基本参数写入设备树。
本质上,它执行与当前 Linux 内核中的“板文件”相同的功能。它还减少了 bootargs 对初始配置的依赖,因为它可以在设备树中提供。有关设备树的更多信息。
要将有关设备地址范围的信息导出到/proc用户空间接口,您必须在驱动程序中将此区域注册到内核:
request_mem_region()