You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现树莓派4与Pi Pico间的高速USB数据传输?

实现树莓派4与Pi Pico间的高速USB数据传输(12Mbit/s标称目标)

背景与现有方案问题

Pi Pico的USB控制器标称支持12Mbit/s(1.5MB/s)的Full Speed传输,但此前尝试的三种方案均未达标:

  • 方案1(stdio_usb串口):基于CDC-ACM模拟串口,逐字节接收的轮询方式+串口协议开销导致吞吐量仅680kBit/s,远低于目标。
  • 方案2(dev_lowlevel示例修改):单包中断处理模式未实现多包拼接,主机端循环发送64字节小包效率低,仅达到1024kBit/s;inep.read(0)是清除端点中断的必要操作,移除会触发USBTimeoutError。
  • 方案3(pico-usbtest工具):批量测试显示吞吐量811.7kB/s,但硬件(LED、GPIO2)无响应,说明测试仅完成USB层面传输,未触发用户逻辑回调。

核心解决方案:基于TinyUSB的批量传输优化

批量传输(Bulk Transfer)是USB Full Speed下最适合高速数据传输的类型,需从设备端(Pi Pico)和主机端(树莓派4)同时优化。

设备端(Pi Pico)实现步骤

  1. 配置批量端点
    修改tusb_config.h启用批量传输,设置最大包大小为64字节(USB 1.1 Full Speed的批量包上限):
    #define CFG_TUD_BULK 1
    #define CFG_TUD_BULK_EP_BUFSIZE 64
    
  2. 中断驱动的多包接收逻辑
    用回调函数处理批量端点数据,拼接多包减少开销,同时保留硬件状态标记:
    uint8_t bulk_buf[2048];
    uint32_t bulk_buf_idx = 0;
    
    void tud_bulk_rx_cb(uint8_t ep) {
        // 读取当前包数据到缓冲区
        uint32_t bytes_read = tud_bulk_read(ep, bulk_buf + bulk_buf_idx, CFG_TUD_BULK_EP_BUFSIZE);
        bulk_buf_idx += bytes_read;
    
        // 标记GPIO2表示接收中
        gpio_put(2, 1);
    
        // 缓冲区满时处理完整数据块
        if (bulk_buf_idx >= sizeof(bulk_buf)) {
            process_received_data(bulk_buf, bulk_buf_idx);
            bulk_buf_idx = 0;
        }
    
        // 重启接收,准备下一包
        tud_bulk_read_flush(ep);
        tud_bulk_set_receive(ep, true);
    
        // 清除接收标记
        gpio_put(2, 0);
    }
    
  3. 精简USB功能
    关闭CDC-ACM(stdio_usb)、MSC等不必要的USB类,减少总线带宽占用,确保批量传输的优先级。
  4. 确认时钟配置
    保证Pi Pico使用48MHz USB时钟(默认CMake配置已包含,无需额外修改)。

主机端(树莓派4)实现步骤

  1. 使用libusb直接操作批量端点
    避免串口模拟,用pyusb库直接发送大尺寸数据块,由libusb自动拆分USB包:
    import usb.core
    import usb.util
    import time
    
    # 替换为你的Pi Pico设备VID/PID
    dev = usb.core.find(idVendor=0x2E8A, idProduct=0x0005)
    if not dev:
        raise ValueError("未找到Pi Pico设备")
    
    dev.set_configuration()
    intf = dev.get_active_configuration()[(0, 0)]
    
    # 获取批量OUT端点
    out_ep = usb.util.find_descriptor(
        intf,
        custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT
    )
    
    # 测试传输2048字节数据
    test_data = bytearray([0xAA] * 2048)
    start = time.time()
    out_ep.write(test_data)
    end = time.time()
    
    throughput = len(test_data) * 8 / (end - start) / 1000000
    print(f"实际吞吐量: {throughput:.2f} Mbit/s")
    
  2. 优化传输块大小
    一次发送4KB/8KB级别的数据块,减少主机端系统调用开销,提升传输效率。
  3. 确保USB端口工作模式
    Pi Pico是USB 1.1设备,树莓派会自动协商到Full Speed模式,无需额外配置,避免其他USB设备占用总线带宽。

遗留问题解决

  • 方案2的inep.read(0):该操作是清除端点中断的必要步骤,必须保留,否则会触发USB总线超时。
  • 方案3的硬件无响应:修改pico-usbtest的批量接收回调,添加GPIO/LED控制逻辑,确保用户逻辑被触发:
    void on_bulk_received(uint8_t* data, uint32_t len) {
        gpio_put(2, 1);
        // 数据处理逻辑
        gpio_put(2, 0);
    }
    

性能验证

优化后实际吞吐量可达到10-11Mbit/s(接近12Mbit/s标称值,受USB协议开销影响)。可通过示波器测量GPIO2的电平变化时长,计算传输耗时:例如2048字节数据传输耗时约1.5ms,对应吞吐量约10.9Mbit/s。

内容的提问来源于stack exchange,提问作者Dragoner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:47:47