在Linux中编写设备驱动程序

3

我是一名写设备驱动程序的新手。

我想为ARM平台上的外围设备编写设备驱动程序。

第一个问题:在Linux中,为ARM平台上的外围设备编写设备驱动程序是否与在x86上不同?

第二个问题:我检查了/proc/iomem文件以查看处理器的当前地址映射。然而,并非所有的外围设备(包括我要访问的设备)都存在于该文件中。如何包括外围设备的地址范围?

第三个问题:设备树在编写设备驱动程序中的重要性是什么?

3个回答

5
如果驱动程序在内核源树中不存在,并且设备在设备地址空间中进行了内存映射,则必须在某个地方声明设备资源(地址区域、irq线路)。在旧版本的内核中,这是板文件的责任,但现在它已经转移到了设备树上。
因此,与x86架构的主要区别不在于如何编写驱动程序,而在于如何匹配设备和驱动程序。在x86上,例如有PCI驱动程序和可发现的PCI设备。在ARM上,通常没有这样的自我描述硬件,为了模拟整个设备/驱动程序流程,创建了平台总线。
因此,ARM上的典型设备驱动程序是平台驱动程序,相关设备是平台设备。当前内核中的一个以太网mac驱动程序示例在这里
在上面链接的驱动程序中,驱动程序代码不知道设备位于何处。此信息在探测时使用platform_device对象传递给驱动程序。平台设备可以描述如下(source):
static struct platform_device at91sam9260_eth_device = {
        .name           = "macb",
        .id             = -1,
        .dev            = {
                                .dma_mask               = &eth_dmamask,
                                .coherent_dma_mask      = DMA_BIT_MASK(32),
                                .platform_data          = &eth_data,
        },
        .resource       = eth_resources,
        .num_resources  = ARRAY_SIZE(eth_resources),
};

平台设备可以通过以下c代码创建,也可以在设备树中进行描述。在这两种情况下,在驱动程序探测到设备之前,您不会在proc/iomem中看到任何内容。这与x86世界大多数设备是PCI设备的情况不同。

这是同一设备,但在设备树文件中进行了描述:

               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";
                };

4
1. 只要外设与SoC接口相似(即在两个平台上使用相同的硬件接口),相同的驱动程序就可以在x86和ARM上使用。这是独立于Linux内核核心开发模块化驱动程序的优势。
2. 如果您特定的外设在当前地址映射(/proc/iomem)中不存在,则可能有以下两种可能性:
  • 设备驱动程序尚未加载。
  • 设备使用其他形式的寻址(非内存映射I/O)。

关于外设的任何其他信息?它如何连接到SoC?


3. Linux内核中的设备树用于描述众多硬件(包括芯片上和外围设备)、它们之间的互连性以及适用于在编写设备树的特定平台/板上进行正确配置和初始化的基本参数。

本质上,它执行与当前Linux内核中找到的“board-file”相同的功能。 它还减少了初始配置的bootargs依赖性,因为可以在设备树中提供相同的内容。 有关设备树的更多信息。


设备使用其他形式的寻址--请注意,ARM没有I/O指令或I/O地址空间,因此直接连接的外围设备必须进行内存映射。设备树--可用性取决于内核版本。 - sawdust
SoC拥有ARM926EJS处理器,并采用AMBA AHB系统作为总线组织。 - yildizabdullah
首先,我想访问简单的外设,如GPIO,然后是外部存储控制器(EMC)接口,该接口提供了AHB和片外存储器设备之间的接口。 - yildizabdullah
2
所有这些都严格来说并不是外围设备。相反,它们将是已经存在于SoC板上的外围控制器。如果Linux内核在SoC上得到“官方”支持,则您将在主线源中找到这些控制器块的驱动程序。这只是选择正确配置(defconfig)以启用它们的问题。 - TheCodeArtist
如果Linux内核尚未正式支持SoC,则您可能需要搜索供应商是否提供自己的Linux内核树(其中包含尚未上游到主线内核的更改)。如果不存在这样的树,则最好找到一个现有的SoC,该SoC受到Linux内核支持并且在原理图上类似于目标SoC。然后,您可以逐个拉入其更改并进行必要的修改。 - TheCodeArtist
1
/proc/iomem中的信息来自驱动程序调用request_mem_region()。 - Dražen G.

1
要将设备的地址范围信息导出到/proc用户空间接口中,您需要在驱动程序中将此区域注册到内核中:
request_mem_region()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接