最近使用XILINX的7系列芯片做产品用到了PCIE接口。用到了XDMA的驱动,但是由于强实时性要求,需要自己从更底层研究驱动。
这里作为学习笔记,记录学习过程以及一些过程,算是情景分析。
1,软硬件环境:
使用UBUNTU 16,板子使用的是XTRX的PCIE版。使用dmesg命令查看驱动打印的输出。使用
sudo dmesg -C && dmesg -Tw
这个命令清除之前显示的内容并实时显示新内容
2,挂在驱动时运行情景。
执行命令
sudo insmod ./xtrx.ko
在代码里面找xtrx_init,
可以看到这是静态初始化的代码。也就是说执行insmod命令好这个无参函数就开始执行。我们看看代码具体做了什么。
static int __init xtrx_init(void)
{
int err;
printk(KERN_INFO PFX "liwei ---------------------startup here-------------------- %d\n", __LINE__ );
printk(KERN_INFO PFX "liwei xtrx_init %d\n", __LINE__ );
err = uart_register_driver(&xtrx_uart_driver);
if (err) {
printk(KERN_NOTICE PFX "Unable to initialize UART driver: %d\n", err);
goto failed_uart;
}
err = alloc_chrdev_region(&dev_first, 0, MAX_XTRX_DEVS, DRV_NAME);
if (err) {
printk(KERN_NOTICE PFX "Unable to allocate chrdev region: %d\n", err);
goto failed_chrdev;
}
xtrx_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(xtrx_class)) {
printk(KERN_NOTICE PFX "Unable to register xtrx class\n");
goto failed_setup_cdev;
}
err = pci_register_driver(&xtrx_driver);
if (err) {
printk(KERN_NOTICE PFX "Unable to register PCI driver: %d\n", err);
goto failed_pci;
}
return 0;
failed_pci:
class_unregister(xtrx_class);
class_destroy(xtrx_class);
failed_setup_cdev:
unregister_chrdev_region(dev_first, devices);
failed_chrdev:
uart_unregister_driver(&xtrx_uart_driver);
failed_uart:
return err;
}
这个驱动集成了对多个逻辑外设的控制,其实pcie相关的函数我们只看pci_register_driver就可以。
pci_register_driver()
是 Linux 内核中用于注册 PCI 设备驱动程序的函数。该函数允许内核在设备探测过程中将驱动程序与合适的 PCI 设备进行匹配。下面是一个在内核模块中使用 pci_register_driver()
的基本示例:
///人工智能生成不保证编译通过,供学习参考
#include <linux/pci.h>
/* PCI 设备 ID 表 */
static const struct pci_device_id my_pci_tbl[] = {
{ PCI_DEVICE(0x1234, 0x5678) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, my_pci_tbl);
/* PCI 驱动程序结构 */
static struct pci_driver my_pci_driver = {
.name = "my_pci_driver",
.id_table = my_pci_tbl,
.probe = my_pci_probe,
.remove = my_pci_remove,
};
static int __init my_pci_init(void)
{
return pci_register_driver(&my_pci_driver);
}
static void __exit my_pci_exit(void)
{
pci_unregister_driver(&my_pci_driver);
}
module_init(my_pci_init);
module_exit(my_pci_exit);
在这个例子中,my_pci_tbl
数组定义了驱动程序支持的 PCI 设备 ID。my_pci_driver
结构包含了驱动程序的名称、设备 ID 表以及 probe
和 remove
回调函数。
在模块的初始化函数 (my_pci_init()
) 中调用 pci_register_driver()
函数将驱动程序注册到 PCI 子系统。在模块的退出函数 (my_pci_exit()
) 中调用 pci_unregister_driver()
函数来注销驱动程序。
当在设备探测过程中找到匹配的 PCI 设备时,会调用 my_pci_probe()
函数来初始化设备。当设备被移除时,会调用 my_pci_remove()
函数来清理设备。
pci_register_driver()
函数在成功时返回 0,在失败时返回负的错误码。
上述斜体是拷贝自人工智能聊天工具,
具体到咱们的代码:这里我们看到 module_init指定的函数调用的pcie_register_driver用一个结构进行了初始化,这个初始化结构如下: