SG2002 TPU Device Driver
SG2002 TPU 设备的Rust驱动。
使用 Rust 最小化设备层实现,去除操作系统内核依赖,保留硬件操作逻辑,便于在裸机或自研RustOS上集成运行。
特性
- KernelFns 抽象层:隔离系统相关能力(日志、时间、时钟控制、缓存同步)
- 硬件操作:TDMA/TIU 寄存器访问与控制流程
- DMA 缓冲区执行:支持描述符模式和 PIO 模式
- 挂起/恢复:支持电源管理
- 结构对齐:IOCTL 结构体使用
#[repr(C)]保证 ABI 兼容
代码结构
src/
├── lib.rs # 库入口,类型导出,TpuError 定义
├── types.rs # 数据类型 (DmaHeader, CpuSyncDesc, TpuConfig, TpuTdmaPioInfo)
├── device.rs # TPU 设备核心实现 (TpuDevice)
├── kernel_fns.rs # 内核函数抽象 trait (KernelFns)
├── platform.rs # 平台相关结构 (TdmaReg, TpuRegBackup, 状态解析)
├── pmu.rs # PMU 性能监控 (TpuPmu, PmuSummary)
├── registers.rs # TDMA/TIU 硬件寄存器常量
└── ioctrl.rs # IOCTL 参数结构定义
调用流程
本库的 API 设计参照 Linux 驱动模块的生命周期:
Linux 驱动 vs Rust 库对照
| 维度 | Linux 驱动实现 | Rust 库实现 | StarryOS 适配层 |
|---|---|---|---|
| 设备生命周期 | cvi_tpu_probe/open/remove + platform_tpu_* |
TpuDevice::new/open/platform_init/platform_deinit |
在 /dev/cvi-tpu0 设备对象中持有 TpuDevice |
| 提交入口 | CVITPU_SUBMIT_DMABUF -> cvi_tpu_submit() -> worker -> platform_run_dmabuf() |
直接 run_dmabuf() |
ioctl(CVITPU_SUBMIT_DMABUF) 同步调用 run_dmabuf() |
| 等待入口 | CVITPU_WAIT_DMABUF -> wait_event_interruptible(done_list) |
库不管理 OS 等待队列 | wait_dmabuf 在适配层按 seq_no 查询 done_list |
| 缓存同步 | CVITPU_DMABUF_FLUSH/INVLD(_FD) |
由 KernelFns::dma_sync_for_* 抽象 |
StarryOS 用 fence/ion 信息做同步 |
| 描述符解析 | 内核直接按 C 结构体解析 dma_hdr_t + cvi_cpu_sync_desc_t[] |
parse_dmabuf_view() 统一解析与边界检查 |
适配层调用 parse_dmabuf_view(),不再手写解析 |
| TDMA 完成等待 | 中断完成 + completion 等待 | wait_tdma_done() 紧凑轮询 + 超时 |
由库内部处理,适配层仅接收结果 |
| 超时恢复 | platform_tpu_reset() |
reset() |
run_dmabuf 超时后可由上层执行 reset |
| 挂起恢复 | platform_tpu_suspend/resume |
suspend()/resume() |
可由系统电源管理路径调用 |
常用 ioctl 对照(用户态视角):
| ioctl | Linux 语义 | StarryOS 当前语义 |
|---|---|---|
CVITPU_SUBMIT_DMABUF (_IOC(_IOC_WRITE, 0x70, 0x1, 0x8)) |
提交任务入队 | 同步执行一次 run_dmabuf 并记录 seq_no 结果 |
CVITPU_WAIT_DMABUF (`_IOC(_IOC_READ |
_IOC_WRITE, 0x70, 0x6, 0x8)`) | 按 seq_no 阻塞等待完成 |
CVITPU_DMABUF_FLUSH (nr=0x4) |
CPU -> Device cache sync | 调用 dma_sync_for_device |
CVITPU_DMABUF_INVLD (nr=0x5) |
Device -> CPU cache sync | 调用 dma_sync_for_cpu |
在Rust OS中的调用序列
基于 YOLOv8 on StarryOS 实际运行于SG2002硬件平台的建议集成流程:
-
系统初始化阶段
- 创建
TpuDevice::new(...) - 调用
probe_setting() - 在设备初始化阶段调用一次
platform_init()
- 创建
-
用户态准备阶段(
/dev/ion+/dev/cvi-tpu0)ION_IOC_ALLOC分配 dmabufmmap映射 ion buffer 到用户态CVITPU_DMABUF_INVLD/CVITPU_DMABUF_FLUSH做缓存同步
-
提交执行阶段(核心热路径)
CVITPU_SUBMIT_DMABUF- 驱动侧通过
parse_dmabuf_view()解析 header/descs - 调用
run_dmabuf(paddr, header, descs)
-
等待完成阶段
CVITPU_WAIT_DMABUF- 使用与 submit 一致的
seq_no获取结果
-
可选收尾
- 继续下一帧提交(推荐)
- 设备长时间空闲时再
platform_deinit()
适配的示例代码
// 1. 实现 KernelFns trait
// 2. 设备探测阶段 (probe)
// 3. 中断处理函数
// 4. 执行一次 dmabuf 提交(StarryOS 驱动热路径)
// 5. 电源管理(可选)
// 6. 用户态 ioctl 的典型顺序(伪代码)
KernelFns Trait
实现此 trait 以适配不同运行环境:
精简评估结论:
now_us是硬性必需(超时与轮询逻辑核心依赖)。enable_clocks/disable_clocks/reset保留为可选钩子,符合不同 SoC 的电源域差异。dma_sync_for_device/dma_sync_for_cpu保留为可选钩子,用于兼容有 cache 维护要求的平台。sleep_ms在当前 SG2002 快路径不是必需;已调整为默认空实现,用于降低接入方实现负担。
编译
参考
- 原始 C 驱动的Linux 内核版本:5.10.4
- HAL 实现:
hal/mars(Mars 平台) - 设备树兼容字符串:
cvitek,tpu
SG2002 硬件信息
| 资源 | 描述 |
|---|---|
| TDMA 寄存器 | 设备树 tdma 资源 |
| TIU 寄存器 | 设备树 tiu 资源 |
| 中断 | 平台中断 1 (TDMA) |
| 时钟 | clk_tpu_axi, clk_tpu_fab |
| 复位 | res_tdma, res_tpu, res_tpusys |
说明
- 需要实现
KernelFnstrait 以提供平台相关功能 run_dmabuf实现了hal/mars的核心提交流程- 该库不包含 Linux 设备模型与中断注册逻辑,由 RustOS 操作系统驱动框架提供
- 不支持 TEE (安全执行环境)