一文读懂树莓派 Pico USB:硬件原理、外设架构与 MicroPython 软件控制
1.树莓派 Pico 的 USB 外设概要信息
树莓派 Pico 的 RP2040 芯片包含一个 USB 2.0 控制器,可以作为任何一种方式操作:
- 一个全速设备(12Mbps)
- 一个可以与低速(1.5Mbps)和全速设备通信的主机,包括连接到一个 USB 集线器的多个下游设备
RP2040 芯片内部集成了一个 USB 1.1 PHY 芯片,USB 控制器与芯片的 DP(D+)和 DM(D-)引脚接口通过 PHY 芯片相连接。USB 控制器的硬件实现了了 USB 物理层、数据链路层和一部分事务层的功能,这意味着程序员不需要手动处理复杂的 USB 协议细节。而是将重心放在以下工作上:
- 配置控制器参数,如设备地址、端点等
- 提供数据缓冲区,供控制器收发数据
- 响应控制器的中断事件,如数据传输完成、端点状态变更
USB 控制器有 4kB 的 DPSRAM,用于存储 USB 设备的配置信息和数据缓冲区。
USB 控制器可以工作于两种工作模式:
- 设备模式:
- USB 2.0 兼容的全速设备(12Mbps)
- 它支持最多 32 个端点(在输入和输出方向上分别为 0 → 15)
- 该设备支持控制、等时、批量和中断端点类型,并支持双缓冲
- 在 DPSRAM 中有 3840 字节的可用缓冲空间,相当于 60 × 64 字节的缓冲区
- 主机模式:
- 可以与全速(12Mbps)设备和低速(1.5Mbps)设备进行通信
- 它可以通过 USB 集线器与多个设备进行通信,包括连接到全速集线器的低速设备
- 设备可以在硬件中轮询多达 15 个中断端点
- 中断端点由集线器用于通知主机连接/断开事件,鼠标用于通知主机移动等
USB 外设结构如下:

可以看到,USB 外设主要由以下几个部分组成:
- 集成的USB PHY芯片
- 负责实现 USB 物理层协议,包括电气特性、信号编码、差分传输等
- 提供了 USB DP 和 DM 引脚与控制器数字逻辑之间的电气接口
- USB PHY 驱动 DP 和 DM 引脚发送数据,并对任何传入数据进行差分接收
- USB PHY 向线路状态检测模块提供单端和差分接收数据
- USB 控制器
- 负责实现 USB 设备端的协议栈和端点管理
- 负责数据的接收和发送,以及控制信号的生成和解析
- 缓冲区存储器
- DPSRAM 用于存储控制寄存器和数据缓冲区
- USB 控制器有 4kB(4096 字节)的 DPSRAM(双端口 SRAM)
- DPSRAM 可以作为 32 位宽度的内存访问,地址为 USB 控制器的地址 0(0x50100000)
- DPSRAM 支持 8/16/32 位访问,但不支持设置/清除别名
- 数据缓冲区通常为 64 字节长:
- 对于 Isochronous 同步传输方式,最大缓冲区大小为 1023 字节
- 对于其他传输方式,每个缓冲区的最大大小为 64 字节
- USB 控制器中的 DPSRAM 应被视为异步的,而不是原子的:
- 它是一个双端口 SRAM,意味着处理器有一个端口来读写内存,USB 控制器也有一个端口来读写内存。这意味着处理器和 USB 控制器可以同时访问同一个内存地址。一个可能正在写入,另一个可能正在读取。如果控制器在读取内存时处理器正在写入内存,可能会得到不一致的数据。必须小心避免这种情况
- 线路状态检测模块
- 定义并检测几种线路状态(总线重置、连接、挂起、恢复、数据 1、数据 0 等)
- 线路状态检测模块有几个状态机来检测这些状态,并将事件信号通知给其他硬件组件
- USB 中没有共享时钟信号,因此 RX 数据必须由内部时钟采样
- USB 全速的最大数据速率是 12Mbps。RX 数据以 48MHz 的速度采样,给出 4 个时钟周期来捕获和过滤总线状态,线路状态检测模块将过滤后的 RX 数据分发到串行 RX 引擎
- 接收引擎
- 串行接收引擎负责解码由线路状态检测模块捕获的接收数据。它生成以下信息:
- 入站数据包的 PID(Packet Identifier)
- 入站数据的设备地址 address
- 入站数据的设备端点 endpoint
- 数据字节
- 串行接收引擎还通过对入站数据进行 CRC 校验来检测 RX 数据中的错误。任何错误都会信号通知其他硬件块,并可能引发中断
- 如果在主机模式或设备模式下在数据包传输过程中断开 USB 电缆,硬件会引发错误
- 串行接收引擎负责解码由线路状态检测模块捕获的接收数据。它生成以下信息:
- 发送引擎
- 串行发送引擎是串行接收引擎的镜像。它连接到当前活动的控制器(无论是设备还是主机)。它创建 TOKEN 和 DATA 数据包,包括计算 CRC,并在总线上传输它们
2.软件控制方法
对于 MicroPython 而言,它将 USB 设备划分为以下两种:
- "Runtime" USB 设备:
- 使用 Python API (
USBDevice类)在 MicroPython 启动后定义; - 需要在运行时配置和激活。
- 使用 Python API (
- "Built-in" USB 设备:
- 编译到 MicroPython 固件中,始终可用;
- 通常包括 USB-CDC (串口) 和可选的 USB-MSC (大容量存储);
- 开箱即用,无需额外配置。
MicroPython 提供了用于实现 USB 设备驱动的底层 Python API 的 USBDevice 类:
- 构造函数:
USBDevice是一个单例类,每次调用构造函数都返回相同的对象引用;
- 主要方法:
config()方法用于配置 USB 设备的描述符和回调函数;active()方法用于激活和停用 runtime USB 设备;builtin_driver属性用于获取/设置内置 USB 驱动配置;remote_wakeup()方法用于唤醒处于挂起状态的 USB 主机;submit_xfer()方法用于提交非控制传输;stall()方法用于设置和获取端点的 STALL 状态;
- 常量:
BUILTIN_NONE,BUILTIN_DEFAULT,BUILTIN_CDC,BUILTIN_MSC,BUILTIN_CDC_MSC代表不同的内置 USB 驱动配置
遗憾的是,根据如下链接中的回答,我们可以看到对树莓派 Pico 来说,无法像使用 STM32 芯片的 PyBoard 一样使用 USBDevice 类控制"Runtime" USB 设备:
https://github.com/micropython/micropython/issues/6811

但是联想到我们在介绍 REPL 交互式解释器中内容,在树莓派 Pico 上,MicroPython 固件默认包含了内置的 USB-CDC 设备驱动,提供了一个虚拟的串口通信通道,这个 USB-CDC 设备是集成在 MicroPython 固件中的"Built-in"设备,无需额外的配置就可以使用。这意味着,我们可以使用该虚拟串口配合系统输入输出就可以完成 USB 数据传输。

树莓派 Pico 的 RP2040 芯片包含一个 USB 2.0 控制器,可以作为任何一种方式操作:
* 一个全速设备(12Mbps)
* 一个可以与低速(1.5Mbps)和全速设备通信的主机,包括连接到一个 USB 集线器的多个下游设备
浙公网安备 33010602011771号