基于 Hello Word 设备树的设备驱动程序
Hello Word Device Tree Based device driver
我已经阅读并几乎通读了所有关于设备树和设备树的 linux 内核文档 overlays.I 我无法理解我们是否必须在设备树中创建一个新的入口平台或为基于设备树的新驱动程序的设备创建新的覆盖。
我正在寻找一个简单的 LED 发光驱动程序示例,其中 LED 连接到 GPIO 引脚,其配置在设备树覆盖或设备树片段中提到 platform.How 可以是 build/pushed 并使用测试用户 space 应用程序。
我在我的设备树中创建了一个自定义设备:
my_device@ffdf0000 {
compatible = "my_driver";
reg = <0xffdf0000 0x1000>
/*
* reg = address of device and size
* (Minimum is System's Pagesize = 0x1000 Byte in my case
*/
}
我为此设备编写了一个内核存根:
(这里我以kernel_src/drivers/uio/uio_pdrv_genirq.c
和Hans J. Koch: Userspace I/O drivers in a realtime context
(设备驱动教程)为基础。)
这个存根有以下两个结构:
of_device_id 结构:
static struct of_device_id my_match_table[] = {
{
.compatible = "my_driver",
},
{0}
};
MODULE_DEVICE_TABLE(of, my_match_table);
和驱动程序结构本身:
static struct platform_driver my_platform_driver = {
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "my_driver",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(my_match_table),
},
};
现在我可以在我的探测函数中访问设备树的属性:
static int my_probe(struct platform_device *dev)
{
struct uio_info *uioinfo;
struct resource *r = &dev->resource[0];
[...]
uioinfo->name = dev->dev.of_node->name /* name from device tree: "my_device" */
uioinfo->mem[0].addr = r->start; /* device address from device tree */
uioinfo->mem[0].size = resource_size(r); /* size from device tree */
[...]
}
当 compatible
与内核存根的条目和设备树都匹配时,将调用探测函数。
将 QEMU 与最小的自定义硬件设备一起使用
我建议你编写自己的最小平台设备,以控制硬件并有一个完整的理解。
我在 GitHub 上提供了一个完整的可运行 Buildroot QEMU 示例和源代码,详见此答案:How to program Linux .dts device tree files?
该示例也记录在 GitHub repository。
我已经阅读并几乎通读了所有关于设备树和设备树的 linux 内核文档 overlays.I 我无法理解我们是否必须在设备树中创建一个新的入口平台或为基于设备树的新驱动程序的设备创建新的覆盖。 我正在寻找一个简单的 LED 发光驱动程序示例,其中 LED 连接到 GPIO 引脚,其配置在设备树覆盖或设备树片段中提到 platform.How 可以是 build/pushed 并使用测试用户 space 应用程序。
我在我的设备树中创建了一个自定义设备:
my_device@ffdf0000 { compatible = "my_driver"; reg = <0xffdf0000 0x1000> /* * reg = address of device and size * (Minimum is System's Pagesize = 0x1000 Byte in my case */ }
我为此设备编写了一个内核存根:
(这里我以
kernel_src/drivers/uio/uio_pdrv_genirq.c
和Hans J. Koch: Userspace I/O drivers in a realtime context
(设备驱动教程)为基础。)这个存根有以下两个结构:
of_device_id 结构:
static struct of_device_id my_match_table[] = { { .compatible = "my_driver", }, {0} }; MODULE_DEVICE_TABLE(of, my_match_table);
和驱动程序结构本身:
static struct platform_driver my_platform_driver = { .probe = my_probe, .remove = my_remove, .driver = { .name = "my_driver", .owner = THIS_MODULE, .of_match_table = of_match_ptr(my_match_table), }, };
现在我可以在我的探测函数中访问设备树的属性:
static int my_probe(struct platform_device *dev) { struct uio_info *uioinfo; struct resource *r = &dev->resource[0]; [...] uioinfo->name = dev->dev.of_node->name /* name from device tree: "my_device" */ uioinfo->mem[0].addr = r->start; /* device address from device tree */ uioinfo->mem[0].size = resource_size(r); /* size from device tree */ [...] }
当 compatible
与内核存根的条目和设备树都匹配时,将调用探测函数。
将 QEMU 与最小的自定义硬件设备一起使用
我建议你编写自己的最小平台设备,以控制硬件并有一个完整的理解。
我在 GitHub 上提供了一个完整的可运行 Buildroot QEMU 示例和源代码,详见此答案:How to program Linux .dts device tree files?
该示例也记录在 GitHub repository。