xHCI驱动学习(0) 模块启动

本文是作者在研读fudan_abc的《USB那些事儿之我是USB Core》后的实践,将探讨xHCI驱动,尤其是xHCI在Linux内核中的实现。xHCI是USB 3.x的host controller规范,主要关注xhci.c和xhci-pci.c文件。文章解释了USB_XHCI_PCI如何作为xHCI驱动和PCI总线驱动之间的接口,并指出xhci-pci模块的初始化过程对于理解整个驱动的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习Linux内核中USB相关内容的实现,读完了fudan_abc大神师兄的《USB那些事儿之我是USB Core》,感觉荡气回肠,因为大神不仅教给我们代码的奥义,也教给我们读代码的奥义。于是接下来尝试用学到的“鱼”和“渔”,从USB Core“启下”,自己学习xHCI驱动的代码。

xHCI是USB 3.x的host controller规范,首先进入drivers/usb/host目录浏览一下,其实从文件名就可以知道,跟xHCI关系最密切的必然是xhci.c。保险起见还是看一下KConfig:

config USB_XHCI_HCD
	tristate "xHCI HCD (USB 3.0) support"
	---help---
	  The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0
	  "SuperSpeed" host controller hardware.

	  To compile this driver as a module, choose M here: the
	  module will be called xhci-hcd.

if USB_XHCI_HCD

config USB_XHCI_PCI
       tristate
       depends on PCI
       default y

config USB_XHCI_PLATFORM
	tristate

config USB_XHCI_MVEBU
	tristate "xHCI support for Marvel
<think>嗯,用户之前已经问过如何分析uboot的usb驱动代码,现在他想进一步了解如何将uboot的xHCI控制器驱动代码移植到ARM裸机环境下运行。我需要先理清楚用户的需求,可能他是在进行某种嵌入式开发,需要在不使用操作系统的情况下直接操作USB硬件,比如在裸机程序中实现USB功能。 首先,我需要回顾uboot中xHCI驱动的结构。uboot的驱动模型虽然类似于Linux,但相对简化,特别是中断处理、内存管理等方面可能有差异。移植到裸机环境需要处理硬件初始化、时钟配置、DMA内存分配等问题,这些在uboot中可能已经通过平台相关的代码处理,但在裸机环境下需要自行实现。 用户可能需要详细的步骤,比如如何提取相关代码,需要修改哪些部分,如何适配硬件平台。同时,用户可能对ARM裸机环境下的开发流程不太熟悉,所以需要分步骤说明,确保每个环节都清晰。 还需要考虑可能的挑战,比如依赖uboot的其他模块(如内存管理、延时函数),如何处理这些依赖,是否有必要替换成裸机环境下的实现。另外,中断处理在裸机中需要自己设置向量表,而uboot可能使用轮询方式,是否需要调整这部分代码。 测试和调试也是关键步骤,用户可能需要知道如何验证移植后的驱动是否正常工作,比如通过USB设备枚举,或者数据传输测试。此外,是否需要硬件调试工具,如JTAG或串口输出调试信息,这些都需要提及。 可能用户的实际应用场景是需要在裸机环境下使用USB功能,比如连接存储设备或HID设备,因此需要确保驱动支持相应的协议。需要指出在移植过程中可能遇到的问题,比如DMA地址对齐、时钟配置错误、PHY初始化等,并给出解决方法。 最后,总结整个流程,强调关键点和注意事项,帮助用户系统地完成移植工作。同时,提醒用户根据具体硬件调整代码,参考芯片手册,确保寄存器配置正确。</think>将U-Boot的xHCI控制器驱动移植到ARM裸机环境需要经过以下系统化流程,我将从代码提取到裸机适配分步骤说明: --- ### 一、代码提取准备 1. **确定目标硬件** - 确认SoC的xHCI控制器版本(如符合xHCI 1.0/1.1规范) - 获取芯片手册中的关键信息: ```c USB_BASE_ADDR = 0xFE200000 // 示例:Raspberry Pi 4 xHCI基地址 USB_IRQ_NUM = 0x60 // 中断号 ``` 2. **提取U-Boot相关代码** ```bash # 关键文件清单 drivers/usb/host/xhci.{c,h} # xHCI核心驱动 drivers/usb/host/xhci-mem.{c,h} # 内存管理 drivers/usb/host/xhci-ring.{c,h} # 传输环处理 include/usb/xhci.h # 寄存器定义 ``` --- ### 二、裸机环境适配步骤 #### 步骤1:硬件初始化层替换 ```c // 替换U-Boot的IO访问函数 #define readl(addr) (*(volatile uint32_t *)(addr)) #define writel(val, addr) (*(volatile uint32_t *)(addr) = (val)) // 新增裸机时钟初始化 void usb_phy_init(void) { /* 参考SoC手册配置USB PHY */ writel(0x80008000, USB_PHY_CTRL_REG); mdelay(100); } ``` #### 步骤2:内存管理改造 ```c // 替换U-Boot的dma_alloc_coherent void *xhci_dma_alloc(size_t size, dma_addr_t *dma) { static void *dma_pool = (void*)0x20000000; // 指定DMA安全内存区域 *dma = (dma_addr_t)dma_pool; dma_pool += ALIGN(size, 4096); return (void*)(*dma); } // 移除原有缓存维护操作(裸机通常不需要) #undef flush_cache #define flush_cache(addr, size) ``` #### 步骤3:中断处理改造 ```c // 裸机中断向量表注册 void xhci_irq_handler(void) { uint32_t status = readl(XHCI_IRQ_STATUS_REG); if (status & XHCI_IRQ_TRB_COMPLETION) { xhci_handle_event(xhci); // 调用原U-Boot事件处理 } writel(status, XHCI_IRQ_STATUS_REG); // 清除中断标志 } // 在裸机启动代码中注册 void irq_init(void) { register_interrupt_handler(USB_IRQ_NUM, xhci_irq_handler); enable_irq(USB_IRQ_NUM); } ``` --- ### 三、关键代码修改点 1. **移除依赖项** - 替换`dev_read_addr()`为直接物理地址: ```c struct xhci_hccr *hccr = (struct xhci_hccr *)USB_BASE_ADDR; ``` 2. **时间系统适配** ```c // 替换U-Boot的timer函数 void mdelay(uint32_t ms) { uint32_t cycles = ms * (CPU_FREQ / 1000); for(volatile uint32_t i=0; i<cycles; i++); } ``` 3. **日志输出改造** ```c // 重定向调试输出到串口 #define xhci_debug(fmt, args...) \ uart_printf("[xHCI] " fmt, ##args) ``` --- ### 四、裸机整合流程 ```c /* main.c */ int main(void) { uart_init(); // 初始化调试串口 usb_phy_init(); // SoC特定PHY初始化 irq_init(); // 启用中断系统 struct xhci_ctrl *ctrl = xhci_get_ctrl(); xhci_init(ctrl); // 初始化xHCI控制器 xhci_hcd_start(ctrl); while(1) { // 插入设备检测逻辑 if(xhci_port_status_changed()) xhci_device_enumeration(); } } ``` --- ### 五、验证阶段 1. **硬件信号测试** - 使用示波器测量USB差分信号DP/DM - 验证VBUS供电(5V/900mA) 2. **枚举测试** ```c // 添加调试代码到xhci_device_enumeration() xhci_debug("Device Connected: VID=%04x PID=%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); ``` 3. **传输测试** ```c // 发起控制传输测试 struct usb_device *udev; usb_control_msg(udev, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 0x0100, 0, buf, 64, 100); ``` --- ### 六、常见问题解决 | 现象 | 排查方向 | 解决方法 | |---------------------|-----------------------------------|-------------------------------| | 控制器无法初始化 | 检查PHY时钟/复位信号 | 验证CRG寄存器配置 | | 设备无法识别 | 分析Setup Packet发送情况 | 抓取USB协议分析仪数据 | | DMA传输错误 | 确认内存对齐(通常需要64B对齐) | 使用xhci_dma_alloc分配内存 | | 中断不触发 | 检查GIC配置与中断屏蔽位 | 添加中断状态寄存器打印 | --- ### 七、代码优化建议 1. **内存管理增强** ```c // 实现动态DMA内存池 #define DMA_POOL_SIZE (4 * 1024 * 1024) __attribute__((aligned(64))) static uint8_t dma_pool[DMA_POOL_SIZE]; ``` 2. **异步传输支持** ```c // 实现事件环处理线程 void xhci_event_thread(void) { while(1) { if(xhci->event_ring->dequeue != xhci->event_ring->enqueue) { process_event(xhci); } } } ``` 移植完成后,可通过USB协议分析仪(如Ellisys)验证协议层交互的正确性,建议从控制传输开始逐步测试批量/中断传输功能。最终应实现USB2.0/3.0设备的枚举和基本数据传输能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值