PCIE驱动学习之1

最近使用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用一个结构进行了初始化,这个初始化结构如下:

这里看到xtrx_pci_table罗列若干对pid和vid这点和USB有点相似。这PID和VID在VIVADO软件里可以对应设置,如下:

这个结构里面还指出了两个函数probe和remove .

从内核打印的输出log里面我们看到了probe函数被调用了,

我们跟进去看看probe的情景

static int xtrx_probe(struct pci_dev *pdev,
			const struct pci_device_id *id)
{
	
	printk(KERN_INFO PFX "liwei xtrx_probe %d\n",  __LINE__ );
	printk(KERN_INFO PFX "liwei --------------------------------------------------- %d\n",  __LINE__ );
	struct xtrx_dev* xtrxdev;
	int err;
	void __iomem* bar0_addr;
	void __iomem* bar1_addr;
	unsigned xtrx_no = devices;

	printk(KERN_INFO PFX "Initializing %s\n", pci_name(pdev));
#ifdef VA_DMA_ADDR_FIXUP
	printk(KERN_INFO PFX "Buggy va/dma mapping on the platform! Fixup enabled\n");
#endif

	err = pci_enable_device(pdev);
	if (err) {
		dev_err(&pdev->dev, "Cannot enable PCI device, "
			"aborting.\n");
		return err;
	}

	/* Reconfigure MaxReadReq to 4KB */
	pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
					   PCI_EXP_DEVCTL_READRQ, PCI_EXP_DEVCTL_READRQ_4096B);

	pci_set_master(pdev);

	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
		dev_err(&pdev->dev,"No suitable consistent DMA available.\n");
		goto err_disable_pdev;
	}

	/*
	 * Check for BARs.  We expect 0: 4KB
	 */
	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
		pci_resource_len(pdev, 0) < 1 << 12) {
		dev_err(&pdev->dev, "Missing UL BAR, aborting.\n");
		err = -ENODEV;
		goto err_disable_pdev;
	}

	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		dev_err(&pdev->dev, "Cannot obtain PCI resources, "
			"aborting.\n");
		goto err_disable_pdev;
	}

	bar0_addr = pci_iomap(pdev, 0,  1 << 12);
	if (!bar0_addr) {
		dev_err(&pdev->dev, "Failed to map BAR 0.\n");
		goto err_free_res;
	}

	bar1_addr = pci_iomap(pdev, 1,  1 << 16);
	if (!bar0_addr) {
		dev_err(&pdev->dev, "Failed to map BAR 0.\n");
		goto err_unmap0;
	}

	xtrxdev = kzalloc(sizeof(*xtrxdev), GFP_KERNEL);
	if (!xtrxdev) {
		dev_err(&pdev->dev, "Failed to allocate memory.\n");
		err = -ENOMEM;
		goto err_unmap1;
	}
	pci_set_drvdata(pdev, xtrxdev);
	xtrxdev->bar0_addr = bar0_addr;
	xtrxdev->bar1_addr = bar1_addr;
	xtrxdev->devno = xtrx_no;
	xtrxdev->pdev = pdev;
	xtrxdev->locked_msk = 0;
	xtrxdev->gps_ctrl_state = 0;
	xtrxdev->sim_ctrl_state = 0;
	xtrxdev->pwr_msk = 0;
	xtrxdev->valid = 0;
	spin_lock_init(&xtrxdev->slock);

	xtrxdev->shared_mmap = (char*)get_zeroed_page(GFP_KERNEL);
	if (!xtrxdev->shared_mmap) {
		dev_err(&pdev->dev, "Failed to allocate kernel mmap memory.\n");
		err = -ENOMEM;
		goto err_alloc0;
	}

	xtrxdev->hwid = xtrx_readl(xtrxdev, GP_PORT_RD_HWCFG);

	xtrxdev->pps = pps_register_source(&xtrx_pps_info,
					PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
	if (!xtrxdev->pps) {
		dev_err(&pdev->dev, "Failed to register 1PPS source.\n");
	}

	init_waitqueue_head(&xtrxdev->queue_ctrl);
	init_waitqueue_head(&xtrxdev->queue_tx);
	init_waitqueue_head(&xtrxdev->queue_rx);
	init_waitqueue_head(&xtrxdev->onepps_ctrl);
	init_waitqueue_head(&xtrxdev->queue_i2c);


#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,0)
	err = pci_enable_msi_range(pdev, XTRX_MSI_COUNT, XTRX_MSI_COUNT);
#else
	err = pci_alloc_irq_vectors(pdev, XTRX_MSI_COUNT, XTRX_MSI_COUNT, PCI_IRQ_MSI);
#endif
	if (err == XTRX_MSI_COUNT) {
		xtrxdev->inttype = XTRX_MSI_4;

		err = request_irq(pdev->irq + INT_1PPS, xtrx_msi_irq_pps, 0, "xtrx_pps", xtrxdev);
		if (err) {
			dev_err(&pdev->dev, "Failed to register CTRL MSI.\n");
			err = -ENODEV;
			goto err_msi;
		}

		err = request_irq(pdev->irq + INT_DMA_TX, xtrx_msi_irq_tx, 0, "xtrx_tx", xtrxdev);
		if (err) {
			dev_err(&pdev->dev, "Failed to register TX MSI.\n");
			err = -ENODEV;
			goto err_irq_0;
		}

		err = request_irq(pdev->irq + INT_DMA_RX, xtrx_msi_irq_rx, 0, "xtrx_rx", xtrxdev);
		if (err) {
			dev_err(&pdev->dev, "Failed to register RX MSI.\n");
			err = -ENODEV;
			goto err_irq_1;
		}

		err = request_irq(pdev->irq + 3, xtrx_msi_irq_other, 0, "xtrx_other", xtrxdev);
		if (err) {
			dev_err(&pdev->dev, "Failed to register OTHER MSI.\n");
			err = -ENODEV;
			goto err_irq_2;
		}
	} else {

#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,0)
		err = pci_enable_msi_range(pdev, 1, 1);
#else
		err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
#endif
		if (err == 1) {
			xtrxdev->inttype = XTRX_MSI_SINGLE;

			err = request_irq(pdev->irq, xtrx_msi_irq_single, 0, "xtrx_msi_single", xtrxdev);
			if (err) {
				dev_err(&pdev->dev, "Failed to register SINGLE MSI.\n");
				err = -ENODEV;
				goto err_msi;
			}	
		} else {
			dev_err(&pdev->dev, "Failed to enable MSI, falling back to legacy mode.\n");
			xtrxdev->inttype = XTRX_LEGACY;

			err = request_irq(pdev->irq, xtrx_irq_legacy, IRQF_SHARED, "xtrx_legacy", xtrxdev);
			if (err) {
				dev_err(&pdev->dev, "Failed to register Legacy interrupt.\n");
				err = -ENODEV;
				goto err_alloc1;
			}
		}
	}

	/* Clear pending interrupts */
	xtrx_readl(xtrxdev, GP_PORT_RD_INTERRUPTS);

	/* Enable interrupts */
	xtrx_writel(xtrxdev, GP_PORT_WR_INT_PCIE, (1U << INT_PCIE_I_FLAG) | 0xfff);

	// Mark that we don't have preallocated buffers
	xtrxdev->buf_rx_size = 0;
	xtrxdev->buf_tx_size = 0;

	memset(xtrxdev->buf_rx, 0, sizeof(xtrxdev->buf_rx));
	memset(xtrxdev->buf_tx, 0, sizeof(xtrxdev->buf_tx));

	err = xtrx_allocdma_rx(xtrxdev, BUF_SIZE);
	if (err) {
		dev_err(&pdev->dev, "Failed to register RX DMA buffers.\n");
		err = -ENODEV;
		goto err_irq_3;
	}

	err = xtrx_allocdma_tx(xtrxdev, BUF_SIZE);
	if (err) {
		dev_err(&pdev->dev, "Failed to register TX DMA buffers.\n");
		err = -ENODEV;
		goto err_rx_bufs;
	}

	err = xtrx_uart_init(xtrxdev, xtrx_no);
	if (err) {
		goto err_uart;
	}

	xtrxdev->valid = 1;
	xtrxdev->cdevice = device_create(xtrx_class,
					 &pdev->dev,
					 MKDEV(MAJOR(dev_first), MINOR(dev_first) + devices),
					 NULL,
					 DEVICE_NAME "%d",
					 devices);
	if (IS_ERR(xtrxdev->cdevice)) {
		printk(KERN_NOTICE PFX "Unable to register device class\n");
		goto failed_device;
	}

	err = xtrx_setup_cdev(xtrxdev);
	if (err) {
		printk(KERN_NOTICE PFX "Error %d initializing cdev\n", err);
		goto failed_cdev;
	}

	devices++;
	xtrxdev->next = xtrx_list;
	xtrx_list = xtrxdev;
	return 0;

	//cdev_del(&xtrxdev->cdev);
failed_cdev:
	device_destroy(xtrx_class, MKDEV(MAJOR(dev_first), MINOR(dev_first) + devices));
failed_device:
	xtrx_uart_deinit(xtrxdev);
err_uart:
	xtrx_freedma_tx(xtrxdev);
err_rx_bufs:
	xtrx_freedma_rx(xtrxdev);
err_irq_3:
	xtrx_writel(xtrxdev, GP_PORT_WR_INT_PCIE, (1U << INT_PCIE_I_FLAG));
	xtrx_readl(xtrxdev, GP_PORT_RD_INTERRUPTS);

	if (xtrxdev->inttype == XTRX_LEGACY) {
		free_irq(pdev->irq, xtrxdev);
	} else if (xtrxdev->inttype == XTRX_MSI_SINGLE) {
		free_irq(pdev->irq, xtrxdev);

		pci_disable_msi(pdev);
	} else if (xtrxdev->inttype == XTRX_MSI_4) {
		free_irq(pdev->irq + 3, xtrxdev);
err_irq_2:
		free_irq(pdev->irq + 2, xtrxdev);
err_irq_1:
		free_irq(pdev->irq + 1, xtrxdev);
err_irq_0:
		free_irq(pdev->irq + 0, xtrxdev);
err_msi:
		pci_disable_msi(pdev);
	}
err_alloc1:
	if (xtrxdev->pps) {
		pps_unregister_source(xtrxdev->pps);
	}
	free_page((unsigned long)xtrxdev->shared_mmap);
err_alloc0:
	kfree(xtrxdev);
err_unmap1:
	pci_iounmap(pdev, bar1_addr);
err_unmap0:
	pci_iounmap(pdev, bar0_addr);
err_free_res:
	pci_release_regions(pdev);

err_disable_pdev:
	pci_clear_master(pdev); /* Nobody seems to do this */

	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
	return err;
};

这就比较多了哈。在开始分析之前最好需要一些基本知识垫底,之后再分析就成了这个基础知识的应用实例了。我们下个blog再写。下面是完整的log信息:


Last login: Fri Jun 28 09:21:16 2024 from 192.168.5.217
za@a:~$sudo dmesg -C &&  dmesg -Tw
[sudo] password for a:
[五 6月 28 09:24:48 2024] xtrx: liwei ---------------------startup here-------------------- 1558
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_init 1559
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_probe 1201
[五 6月 28 09:24:48 2024] xtrx: liwei --------------------------------------------------- 1202
[五 6月 28 09:24:48 2024] xtrx: Initializing 0000:01:00.0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_readl[194] off=0000001a return=04000113
[五 6月 28 09:24:48 2024] pps pps1: new PPS source xtrx_pps
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_readl[194] off=00000001 return=00000000
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000001 d=00008fff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma_rx 682
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma 650
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_set_dma_bufs 621
[五 6月 28 09:24:48 2024] xtrx: buf[0]=21820000 [virt 000000006fc894be] => 218207ff
[五 6月 28 09:24:48 2024] xtrx: buf[1]=21828000 [virt 0000000065f2c3e7] => 218287ff
[五 6月 28 09:24:48 2024] xtrx: buf[2]=21830000 [virt 000000001c1ebb66] => 218307ff
[五 6月 28 09:24:48 2024] xtrx: buf[3]=21838000 [virt 000000005522f2e9] => 218387ff
[五 6月 28 09:24:48 2024] xtrx: buf[4]=21840000 [virt 00000000e09cdfb6] => 218407ff
[五 6月 28 09:24:48 2024] xtrx: buf[5]=21848000 [virt 000000006fce65f0] => 218487ff
[五 6月 28 09:24:48 2024] xtrx: buf[6]=21850000 [virt 000000006018dc4a] => 218507ff
[五 6月 28 09:24:48 2024] xtrx: buf[7]=21858000 [virt 00000000f80e6177] => 218587ff
[五 6月 28 09:24:48 2024] xtrx: buf[8]=21860000 [virt 00000000887b0551] => 218607ff
[五 6月 28 09:24:48 2024] xtrx: buf[9]=21868000 [virt 000000004760bb6e] => 218687ff
[五 6月 28 09:24:48 2024] xtrx: buf[10]=21870000 [virt 00000000a7b9fb64] => 218707ff
[五 6月 28 09:24:48 2024] xtrx: buf[11]=21878000 [virt 0000000040407799] => 218787ff
[五 6月 28 09:24:48 2024] xtrx: buf[12]=21880000 [virt 000000004145c18f] => 218807ff
[五 6月 28 09:24:48 2024] xtrx: buf[13]=21888000 [virt 000000002b334677] => 218887ff
[五 6月 28 09:24:48 2024] xtrx: buf[14]=21890000 [virt 0000000079d1f4c7] => 218907ff
[五 6月 28 09:24:48 2024] xtrx: buf[15]=21898000 [virt 0000000031dac545] => 218987ff
[五 6月 28 09:24:48 2024] xtrx: buf[16]=218a0000 [virt 000000009da889e5] => 218a07ff
[五 6月 28 09:24:48 2024] xtrx: buf[17]=218a8000 [virt 000000000c789d14] => 218a87ff
[五 6月 28 09:24:48 2024] xtrx: buf[18]=218b0000 [virt 00000000ee27b209] => 218b07ff
[五 6月 28 09:24:48 2024] xtrx: buf[19]=218b8000 [virt 00000000ee2a56fa] => 218b87ff
[五 6月 28 09:24:48 2024] xtrx: buf[20]=218c0000 [virt 00000000d3a6e9a5] => 218c07ff
[五 6月 28 09:24:48 2024] xtrx: buf[21]=218c8000 [virt 000000008aa954df] => 218c87ff
[五 6月 28 09:24:48 2024] xtrx: buf[22]=218d0000 [virt 00000000aeaf240e] => 218d07ff
[五 6月 28 09:24:48 2024] xtrx: buf[23]=218d8000 [virt 00000000727a1b04] => 218d87ff
[五 6月 28 09:24:48 2024] xtrx: buf[24]=218e0000 [virt 00000000c61b0dd6] => 218e07ff
[五 6月 28 09:24:48 2024] xtrx: buf[25]=218e8000 [virt 00000000bf5bb660] => 218e87ff
[五 6月 28 09:24:48 2024] xtrx: buf[26]=218f0000 [virt 00000000d371946b] => 218f07ff
[五 6月 28 09:24:48 2024] xtrx: buf[27]=218f8000 [virt 0000000001c30e6d] => 218f87ff
[五 6月 28 09:24:48 2024] xtrx: buf[28]=21900000 [virt 0000000016fc4af6] => 219007ff
[五 6月 28 09:24:48 2024] xtrx: buf[29]=21908000 [virt 0000000019310411] => 219087ff
[五 6月 28 09:24:48 2024] xtrx: buf[30]=21910000 [virt 00000000a8de86a3] => 219107ff
[五 6月 28 09:24:48 2024] xtrx: buf[31]=21918000 [virt 00000000b638a065] => 219187ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_update_rxdma_len 637
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000220 d=800007ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma_tx 669
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_allocdma 650
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_set_dma_bufs 621
[五 6月 28 09:24:48 2024] xtrx: buf[0]=21920000 [virt 00000000860cc5d5] => 219207ff
[五 6月 28 09:24:48 2024] xtrx: buf[1]=21928000 [virt 00000000f83b63c8] => 219287ff
[五 6月 28 09:24:48 2024] xtrx: buf[2]=21930000 [virt 00000000e330ff31] => 219307ff
[五 6月 28 09:24:48 2024] xtrx: buf[3]=21938000 [virt 00000000201b4ddb] => 219387ff
[五 6月 28 09:24:48 2024] xtrx: buf[4]=21940000 [virt 00000000fca0f5ce] => 219407ff
[五 6月 28 09:24:48 2024] xtrx: buf[5]=21948000 [virt 000000006fec8be3] => 219487ff
[五 6月 28 09:24:48 2024] xtrx: buf[6]=21950000 [virt 000000001bf9e18b] => 219507ff
[五 6月 28 09:24:48 2024] xtrx: buf[7]=21958000 [virt 00000000c42130e0] => 219587ff
[五 6月 28 09:24:48 2024] xtrx: buf[8]=21960000 [virt 0000000026d14254] => 219607ff
[五 6月 28 09:24:48 2024] xtrx: buf[9]=21968000 [virt 00000000215fc23b] => 219687ff
[五 6月 28 09:24:48 2024] xtrx: buf[10]=21970000 [virt 00000000af93cabe] => 219707ff
[五 6月 28 09:24:48 2024] xtrx: buf[11]=21978000 [virt 0000000077a34b82] => 219787ff
[五 6月 28 09:24:48 2024] xtrx: buf[12]=21980000 [virt 000000001ffe1ef5] => 219807ff
[五 6月 28 09:24:48 2024] xtrx: buf[13]=21988000 [virt 00000000b2206b69] => 219887ff
[五 6月 28 09:24:48 2024] xtrx: buf[14]=21990000 [virt 0000000016188eac] => 219907ff
[五 6月 28 09:24:48 2024] xtrx: buf[15]=21998000 [virt 0000000033d73a66] => 219987ff
[五 6月 28 09:24:48 2024] xtrx: buf[16]=219a0000 [virt 0000000061dcb081] => 219a07ff
[五 6月 28 09:24:48 2024] xtrx: buf[17]=219a8000 [virt 00000000a4415696] => 219a87ff
[五 6月 28 09:24:48 2024] xtrx: buf[18]=219b0000 [virt 00000000147bf061] => 219b07ff
[五 6月 28 09:24:48 2024] xtrx: buf[19]=219b8000 [virt 000000002b96edbc] => 219b87ff
[五 6月 28 09:24:48 2024] xtrx: buf[20]=219c0000 [virt 00000000171aed14] => 219c07ff
[五 6月 28 09:24:48 2024] xtrx: buf[21]=219c8000 [virt 00000000c4d6b7b7] => 219c87ff
[五 6月 28 09:24:48 2024] xtrx: buf[22]=219d0000 [virt 000000001f8137c3] => 219d07ff
[五 6月 28 09:24:48 2024] xtrx: buf[23]=219d8000 [virt 00000000b4355c52] => 219d87ff
[五 6月 28 09:24:48 2024] xtrx: buf[24]=219e0000 [virt 0000000064b5a531] => 219e07ff
[五 6月 28 09:24:48 2024] xtrx: buf[25]=219e8000 [virt 00000000e5b35ea8] => 219e87ff
[五 6月 28 09:24:48 2024] xtrx: buf[26]=219f0000 [virt 0000000081287884] => 219f07ff
[五 6月 28 09:24:48 2024] xtrx: buf[27]=219f8000 [virt 00000000506c4344] => 219f87ff
[五 6月 28 09:24:48 2024] xtrx: buf[28]=21a00000 [virt 000000005a8f5b48] => 21a007ff
[五 6月 28 09:24:48 2024] xtrx: buf[29]=21a08000 [virt 000000000f3a8421] => 21a087ff
[五 6月 28 09:24:48 2024] xtrx: buf[30]=21a10000 [virt 000000009212845c] => 21a107ff
[五 6月 28 09:24:48 2024] xtrx: buf[31]=21a18000 [virt 0000000077661f83] => 21a187ff
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_init 567
[五 6月 28 09:24:48 2024] xtrx: Port config: 0 (1)
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_request_port [395]
[五 6月 28 09:24:48 2024] xtrx: Port request: 0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_type [388]
[五 6月 28 09:24:48 2024] 0000:01:00.0: ttyXTRX0 at MMIO 0x0 (irq = 0, base_baud = 9600) is a xtrx_uart
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_set_mctrl [266]
[五 6月 28 09:24:48 2024] xtrx: Port config: 1 (1)
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_request_port [395]
[五 6月 28 09:24:48 2024] xtrx: Port request: 1
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_type [388]
[五 6月 28 09:24:48 2024] 0000:01:00.0: ttyXTRX1 at MMIO 0x0 (irq = 0, base_baud = 9600) is a xtrx_uart
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_uart_set_mctrl [266]
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_dev_from_uart_port[252]
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_writel[187] off=00000006 d=00000000
[五 6月 28 09:24:48 2024] xtrx: SIM mctrl=0
[五 6月 28 09:24:48 2024] xtrx: liwei xtrx_setup_cdev 1188

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VxWorks PCIe驱动程序开发 PDF是一本关于VxWorks操作系统下开发PCI Express接口设备驱动程序的PDF格式电子书籍。该书涵盖了各种相关的主题,包括PCIe总线结构、PCIe设备的驱动开发方法、VxWorks操作系统中PCIe驱动程序的编写和调试等内容。 首先,PCIe总线结构是现代计算机系统中用于高速数据传输的通信总线之一。了解PCIe总线结构对于进行PCIe设备驱动程序的开发至关重要。本书详细介绍了PCIe总线的基本知识、术语和工作原理,帮助读者了解该总线的特点和性能。 其次,本书详细介绍了在VxWorks操作系统中开发PCIe设备驱动程序的方法。它涵盖了驱动程序的基本概念、VxWorks驱动程序框架、设备初始化和资源分配、驱动程序的读写操作以及中断处理等方面的内容。读者可以通过本书学习到如何使用VxWorks提供的API和工具来开发高效可靠的PCIe驱动程序。 最后,在开发过程中,驱动程序的调试是非常重要的一步。本书提供了一些常用的调试技术和工具,帮助开发人员快速定位和解决问题。此外,本书还介绍了一些常见的PCIe设备的驱动程序开发案例,并给出了相应的源码和演示程序,帮助读者更好地理解和应用书中的知识。 总的来说,VxWorks PCIe驱动程序开发PDF是一本全面而实用的教材,适合有一定嵌入式系统开发经验的工程师和学者阅读。通过学习该书,读者可以掌握在VxWorks操作系统中开发PCIe设备驱动程序的基本原理和方法,提高驱动程序开发的效率和质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值