云计算百科
云计算领域专业知识百科平台

解剖USB控制器移植:从VeriSilicon到MindMotion的“外科手术式”改造

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:通信协议,本专栏为记录项目中用到的知识点,以及一些硬件常识总结 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

在这里插入图片描述

🧩 解剖USB控制器移植:从VeriSilicon到MindMotion的“外科手术式”改造

一句话定性:这不是简单的换芯片,而是把一台“自动挡汽车”的发动机,移植到一台“手动挡赛车”上——前者油门刹车自动匹配,后者换挡离合全靠驾驶员(代码)精准操作。


第一章:先看“手术现场”——两份代码揭示的架构DNA

提供的两份usbreg.c,恰好是一次真实的生产级移植:从MM32L052(VeriSilicon USB IP)移植到MM32F0160(MindMotion MCF OTG IP)。通过代码差异,我们能反向工程出两个IP核在设计哲学上的根本不同。

🔬 代码解剖:一眼看出架构差异

代码特征MM32L052(VeriSilicon IP)MM32F0160(MindMotion BDT)
中断处理 细粒度中断:EP_IN_NACK、EP_OUT_ACK、EP_SETUP、EP_STALL 单一USB_INT_TOKENDONE统一处理
数据搬运 直接FIFO读写:USB_EP0_FIFO BDT表 + DMA:需要填充ADDR、BC、OWN
端点控制 写寄存器触发:USB_EP0_CTRL = 0x80 + 长度 手动Arm BDT:usb_bdt_arm() + ep0_tx_busy
收发缓冲 硬件FIFO自动管理 软件双缓冲:ep0_txbuf、ep0_rxbuf + ep_next_odd
总线复位 软件写寄存器:USB_USBRST 硬件自动产生USB_INT_RESET中断

第二章:架构差异的“灵魂”对比

🚗 VeriSilicon IP——“傻瓜式自动挡”

设计哲学:把复杂的USB协议栈硬件化,让开发者像操作UART一样简单。

#mermaid-svg-qSCp3X40pBZ1O035{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qSCp3X40pBZ1O035 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qSCp3X40pBZ1O035 .error-icon{fill:#552222;}#mermaid-svg-qSCp3X40pBZ1O035 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qSCp3X40pBZ1O035 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qSCp3X40pBZ1O035 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qSCp3X40pBZ1O035 .marker.cross{stroke:#333333;}#mermaid-svg-qSCp3X40pBZ1O035 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qSCp3X40pBZ1O035 p{margin:0;}#mermaid-svg-qSCp3X40pBZ1O035 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-qSCp3X40pBZ1O035 .cluster-label text{fill:#333;}#mermaid-svg-qSCp3X40pBZ1O035 .cluster-label span{color:#333;}#mermaid-svg-qSCp3X40pBZ1O035 .cluster-label span p{background-color:transparent;}#mermaid-svg-qSCp3X40pBZ1O035 .label text,#mermaid-svg-qSCp3X40pBZ1O035 span{fill:#333;color:#333;}#mermaid-svg-qSCp3X40pBZ1O035 .node rect,#mermaid-svg-qSCp3X40pBZ1O035 .node circle,#mermaid-svg-qSCp3X40pBZ1O035 .node ellipse,#mermaid-svg-qSCp3X40pBZ1O035 .node polygon,#mermaid-svg-qSCp3X40pBZ1O035 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qSCp3X40pBZ1O035 .rough-node .label text,#mermaid-svg-qSCp3X40pBZ1O035 .node .label text,#mermaid-svg-qSCp3X40pBZ1O035 .image-shape .label,#mermaid-svg-qSCp3X40pBZ1O035 .icon-shape .label{text-anchor:middle;}#mermaid-svg-qSCp3X40pBZ1O035 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qSCp3X40pBZ1O035 .rough-node .label,#mermaid-svg-qSCp3X40pBZ1O035 .node .label,#mermaid-svg-qSCp3X40pBZ1O035 .image-shape .label,#mermaid-svg-qSCp3X40pBZ1O035 .icon-shape .label{text-align:center;}#mermaid-svg-qSCp3X40pBZ1O035 .node.clickable{cursor:pointer;}#mermaid-svg-qSCp3X40pBZ1O035 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qSCp3X40pBZ1O035 .arrowheadPath{fill:#333333;}#mermaid-svg-qSCp3X40pBZ1O035 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qSCp3X40pBZ1O035 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qSCp3X40pBZ1O035 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qSCp3X40pBZ1O035 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qSCp3X40pBZ1O035 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qSCp3X40pBZ1O035 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qSCp3X40pBZ1O035 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qSCp3X40pBZ1O035 .cluster text{fill:#333;}#mermaid-svg-qSCp3X40pBZ1O035 .cluster span{color:#333;}#mermaid-svg-qSCp3X40pBZ1O035 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qSCp3X40pBZ1O035 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qSCp3X40pBZ1O035 rect.text{fill:none;stroke-width:0;}#mermaid-svg-qSCp3X40pBZ1O035 .icon-shape,#mermaid-svg-qSCp3X40pBZ1O035 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qSCp3X40pBZ1O035 .icon-shape p,#mermaid-svg-qSCp3X40pBZ1O035 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qSCp3X40pBZ1O035 .icon-shape .label rect,#mermaid-svg-qSCp3X40pBZ1O035 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qSCp3X40pBZ1O035 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qSCp3X40pBZ1O035 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qSCp3X40pBZ1O035 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

VeriSilicon USB IP

CPU

硬件FIFO

硬件SIE引擎

PHY物理层

USB总线

关键特征:

  • 中断丰富:每个USB事件都有独立中断标志(SETUP、IN_NACK、OUT_ACK、STALL),开发者不需要轮询
  • FIFO直通:写USB_EP0_FIFO寄存器,数据自动进入发送队列
  • 硬件状态机:控制传输的SETUP→DATA→STATUS阶段,硬件自动管理
  • 代码证据:

    // L052: 简单!写FIFO就发数据
    write_mreg32(USB_EP0_FIFO, data_byte); // 直接写到硬件FIFO
    write_mreg32(USB_EP0_CTRL, 0x80 | len); // 触发发送


    🏎️ MindMotion BDT——“手动挡赛车”

    设计哲学:把控制权完全交给软件,硬件只做“无脑搬运工”。

    #mermaid-svg-h75hMG60ETXekxSe{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-h75hMG60ETXekxSe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-h75hMG60ETXekxSe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-h75hMG60ETXekxSe .error-icon{fill:#552222;}#mermaid-svg-h75hMG60ETXekxSe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-h75hMG60ETXekxSe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-h75hMG60ETXekxSe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-h75hMG60ETXekxSe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-h75hMG60ETXekxSe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-h75hMG60ETXekxSe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-h75hMG60ETXekxSe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-h75hMG60ETXekxSe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-h75hMG60ETXekxSe .marker.cross{stroke:#333333;}#mermaid-svg-h75hMG60ETXekxSe svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-h75hMG60ETXekxSe p{margin:0;}#mermaid-svg-h75hMG60ETXekxSe .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-h75hMG60ETXekxSe .cluster-label text{fill:#333;}#mermaid-svg-h75hMG60ETXekxSe .cluster-label span{color:#333;}#mermaid-svg-h75hMG60ETXekxSe .cluster-label span p{background-color:transparent;}#mermaid-svg-h75hMG60ETXekxSe .label text,#mermaid-svg-h75hMG60ETXekxSe span{fill:#333;color:#333;}#mermaid-svg-h75hMG60ETXekxSe .node rect,#mermaid-svg-h75hMG60ETXekxSe .node circle,#mermaid-svg-h75hMG60ETXekxSe .node ellipse,#mermaid-svg-h75hMG60ETXekxSe .node polygon,#mermaid-svg-h75hMG60ETXekxSe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-h75hMG60ETXekxSe .rough-node .label text,#mermaid-svg-h75hMG60ETXekxSe .node .label text,#mermaid-svg-h75hMG60ETXekxSe .image-shape .label,#mermaid-svg-h75hMG60ETXekxSe .icon-shape .label{text-anchor:middle;}#mermaid-svg-h75hMG60ETXekxSe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-h75hMG60ETXekxSe .rough-node .label,#mermaid-svg-h75hMG60ETXekxSe .node .label,#mermaid-svg-h75hMG60ETXekxSe .image-shape .label,#mermaid-svg-h75hMG60ETXekxSe .icon-shape .label{text-align:center;}#mermaid-svg-h75hMG60ETXekxSe .node.clickable{cursor:pointer;}#mermaid-svg-h75hMG60ETXekxSe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-h75hMG60ETXekxSe .arrowheadPath{fill:#333333;}#mermaid-svg-h75hMG60ETXekxSe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-h75hMG60ETXekxSe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-h75hMG60ETXekxSe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h75hMG60ETXekxSe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-h75hMG60ETXekxSe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h75hMG60ETXekxSe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-h75hMG60ETXekxSe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-h75hMG60ETXekxSe .cluster text{fill:#333;}#mermaid-svg-h75hMG60ETXekxSe .cluster span{color:#333;}#mermaid-svg-h75hMG60ETXekxSe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-h75hMG60ETXekxSe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-h75hMG60ETXekxSe rect.text{fill:none;stroke-width:0;}#mermaid-svg-h75hMG60ETXekxSe .icon-shape,#mermaid-svg-h75hMG60ETXekxSe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h75hMG60ETXekxSe .icon-shape p,#mermaid-svg-h75hMG60ETXekxSe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-h75hMG60ETXekxSe .icon-shape .label rect,#mermaid-svg-h75hMG60ETXekxSe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h75hMG60ETXekxSe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-h75hMG60ETXekxSe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-h75hMG60ETXekxSe :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    MindMotion BDT架构

    CPU

    BDT描述符表内存中的任务清单

    DMA引擎

    系统内存缓冲区

    SIE引擎

    PHY物理层

    USB总线

    关键特征:

  • 单一中断:所有传输完成统一触发USB_INT_TOKENDONE,软件必须读取BDT判断是哪个端点、什么方向
  • BDT驱动:每次传输前,必须填充BDT表的ADDR(缓冲区地址)、BC(字节数)、OWN(所有权标志)
  • 双缓冲乒乓:软件必须管理even/odd两个缓冲区的切换,类似“双倍缓冲手写笔迹”
  • 代码证据:

    // F0160: 复杂!手动填充BDT,手动管理双缓冲
    odd = ep_next_odd[0][USB_Direction_IN]; // 选奇偶缓冲
    usb_bdt_arm(&usb_bd_tbl.Table[0][USB_Direction_IN][odd],
    ep_data_n[0][USB_Direction_IN], // DATA0/DATA1
    usb_ep0_txbuf, // 缓冲区地址
    val & 0x7f); // 长度
    ep_next_odd[0][USB_Direction_IN] ^= 1; // 切换奇偶
    ep0_tx_busy = 1; // 软件锁


    第三章:核心机制深度拆解

    🔄 中断处理机制对比

    事件VeriSilicon(L052)MindMotion(F0160)
    SETUP包到达 独立EP_SETUP中断 TOKDONE中断中读取token类型判断
    IN数据发送 EP_IN_NACK中断 TOKDONE中通过dir==IN判断
    OUT数据接收 EP_OUT_ACK中断 TOKDONE中通过dir==OUT判断
    传输完成 EP_FINISH中断 同上TOKDONE
    STALL握手 EP_STALL独立中断 USB_INT_STALL独立中断

    流程图对比:

    #mermaid-svg-Vst1Psum4wQYuClY{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Vst1Psum4wQYuClY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Vst1Psum4wQYuClY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Vst1Psum4wQYuClY .error-icon{fill:#552222;}#mermaid-svg-Vst1Psum4wQYuClY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Vst1Psum4wQYuClY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Vst1Psum4wQYuClY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Vst1Psum4wQYuClY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Vst1Psum4wQYuClY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Vst1Psum4wQYuClY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Vst1Psum4wQYuClY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Vst1Psum4wQYuClY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Vst1Psum4wQYuClY .marker.cross{stroke:#333333;}#mermaid-svg-Vst1Psum4wQYuClY svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Vst1Psum4wQYuClY p{margin:0;}#mermaid-svg-Vst1Psum4wQYuClY .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Vst1Psum4wQYuClY .cluster-label text{fill:#333;}#mermaid-svg-Vst1Psum4wQYuClY .cluster-label span{color:#333;}#mermaid-svg-Vst1Psum4wQYuClY .cluster-label span p{background-color:transparent;}#mermaid-svg-Vst1Psum4wQYuClY .label text,#mermaid-svg-Vst1Psum4wQYuClY span{fill:#333;color:#333;}#mermaid-svg-Vst1Psum4wQYuClY .node rect,#mermaid-svg-Vst1Psum4wQYuClY .node circle,#mermaid-svg-Vst1Psum4wQYuClY .node ellipse,#mermaid-svg-Vst1Psum4wQYuClY .node polygon,#mermaid-svg-Vst1Psum4wQYuClY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Vst1Psum4wQYuClY .rough-node .label text,#mermaid-svg-Vst1Psum4wQYuClY .node .label text,#mermaid-svg-Vst1Psum4wQYuClY .image-shape .label,#mermaid-svg-Vst1Psum4wQYuClY .icon-shape .label{text-anchor:middle;}#mermaid-svg-Vst1Psum4wQYuClY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Vst1Psum4wQYuClY .rough-node .label,#mermaid-svg-Vst1Psum4wQYuClY .node .label,#mermaid-svg-Vst1Psum4wQYuClY .image-shape .label,#mermaid-svg-Vst1Psum4wQYuClY .icon-shape .label{text-align:center;}#mermaid-svg-Vst1Psum4wQYuClY .node.clickable{cursor:pointer;}#mermaid-svg-Vst1Psum4wQYuClY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Vst1Psum4wQYuClY .arrowheadPath{fill:#333333;}#mermaid-svg-Vst1Psum4wQYuClY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Vst1Psum4wQYuClY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Vst1Psum4wQYuClY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vst1Psum4wQYuClY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Vst1Psum4wQYuClY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vst1Psum4wQYuClY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Vst1Psum4wQYuClY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Vst1Psum4wQYuClY .cluster text{fill:#333;}#mermaid-svg-Vst1Psum4wQYuClY .cluster span{color:#333;}#mermaid-svg-Vst1Psum4wQYuClY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Vst1Psum4wQYuClY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Vst1Psum4wQYuClY rect.text{fill:none;stroke-width:0;}#mermaid-svg-Vst1Psum4wQYuClY .icon-shape,#mermaid-svg-Vst1Psum4wQYuClY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vst1Psum4wQYuClY .icon-shape p,#mermaid-svg-Vst1Psum4wQYuClY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Vst1Psum4wQYuClY .icon-shape .label rect,#mermaid-svg-Vst1Psum4wQYuClY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vst1Psum4wQYuClY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Vst1Psum4wQYuClY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Vst1Psum4wQYuClY :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    MindMotion:单一TOKDONE

    USB中断

    判断中断类型

    TOKDONE → 统一处理

    读取BDT获取端点/方向/token

    根据token分发到SETUP/IN/OUT

    VeriSilicon:多路并行中断

    USB中断

    判断中断类型

    EP_SETUP → SETUP处理

    EP_IN_NACK → IN处理

    EP_OUT_ACK → OUT处理

    EP_STALL → STALL处理


    📦 数据传输路径对比

    VeriSilicon:寄存器直通模式

    // 发送数据:简单寄存器操作
    void usb_send_ep0(uint8 *data, uint8 len) {
    for (i=0; i<len; i++) {
    write_mreg32(USB_EP0_FIFO, data[i]); // 逐个写入FIFO
    }
    write_mreg32(USB_EP0_CTRL, 0x80 | len); // 启动发送
    }

    MindMotion:BDT+DMA模式

    // 发送数据:复杂的BDT配置流程
    void usb_send_ep0(uint8 *data, uint8 len) {
    // 1. 先拷贝到软件缓冲区
    memcpy(usb_ep0_txbuf, data, len);

    // 2. 选哪个BDT槽位(even/odd乒乓)
    uint8 odd = ep_next_odd[0][USB_Direction_IN];

    // 3. 填充BDT描述符
    usb_bdt_arm(&usb_bd_tbl.Table[0][USB_Direction_IN][odd],
    ep_data_n[0][USB_Direction_IN],
    usb_ep0_txbuf,
    len);

    // 4. 切换下一个槽位
    ep_next_odd[0][USB_Direction_IN] ^= 1;

    // 5. 软件锁(防重入)
    ep0_tx_busy = 1;
    }


    🧠 控制传输状态机差异

    USB控制传输有三个必经阶段:SETUP → DATA(可选)→ STATUS。两个IP对状态机的管理方式截然不同:

    阶段VeriSilicon(硬件管理)MindMotion(软件管理)
    SETUP 硬件收到SETUP后触发EP_SETUP中断,同时自动切换到下一个状态 软件在TOKDONE中检测到SETUP token后,手动配置下一个BDT接收/发送
    DATA 硬件根据wLength自动决定IN/OUT事务 软件根据SETUP包内容,手动填充BDT启动IN或OUT
    STATUS 硬件自动发送/接收ZLP,完成后触发EP_FINISH 软件在DATA阶段完成后,手动调用usb_ep0_tx_zlp()发送状态包

    代码证据:移植代码中最微妙的地方——SETUP处理完后,需要手动兜底发送状态ZLP:

    // F0160移植代码中的关键修补:无数据阶段的ZLP兜底
    if ((wLength == 0) &&
    !USB_BufDesp_IsBusy(&usb_bd_tbl.Table[0][USB_Direction_IN][0]) &&
    !USB_BufDesp_IsBusy(&usb_bd_tbl.Table[0][USB_Direction_IN][1]))
    {
    usb_ep0_tx_zlp(); // 手动发送零长度状态包!
    usb_running_ctrl_state = USB_IDLE;
    }

    这段代码在VeriSilicon版本中根本不需要,因为硬件自动完成了!


    第四章:移植工作量全景对比

    #mermaid-svg-sauGlcT3S7gYRZM1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sauGlcT3S7gYRZM1 .error-icon{fill:#552222;}#mermaid-svg-sauGlcT3S7gYRZM1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sauGlcT3S7gYRZM1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sauGlcT3S7gYRZM1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sauGlcT3S7gYRZM1 .marker.cross{stroke:#333333;}#mermaid-svg-sauGlcT3S7gYRZM1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sauGlcT3S7gYRZM1 p{margin:0;}#mermaid-svg-sauGlcT3S7gYRZM1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    USB IP移植工作量分布

    中断重映射

    BDT管理

    控制传输适配

    双缓冲管理

    调试

    20

    18

    16

    14

    12

    10

    8

    6

    4

    2

    0

    工作量(人天)

    移植任务工作量难点说明
    中断重映射 ⭐⭐ 把细粒度中断合并到TOKDONE,需要重写中断分发逻辑
    BDT管理 ⭐⭐⭐⭐⭐ 需要实现usb_bdt_arm()、奇偶切换、OWN位管理
    控制传输适配 ⭐⭐⭐⭐⭐ SETUP→DATA→STATUS状态机完全由软件维护,必须吃透USB协议
    双缓冲管理 ⭐⭐⭐⭐ 软件维护ep_next_odd、ep_tx_busy等状态标志
    调试 ⭐⭐⭐⭐⭐ BDT调试只能看内存+逻辑分析仪,问题定位极其困难

    第五章:为什么MindMotion要做这种“反人性”设计?

    🎯 三个核心原因:

  • 降低硬件成本:硬件FIFO和复杂状态机占用大量硅面积,BDT方式用软件逻辑代替硬件逻辑,芯片更小、更便宜
  • 极致灵活性:开发者可以“绕开”标准USB协议,实现自定义行为(比如模拟复合设备、非标准端点行为)
  • DMA效率:BDT+DMA方式在大批量数据时效率更高,CPU不需要参与每个字节的搬运(VeriSilicon的FIFO模式在高速下CPU负担重)
  • 📊 适用场景对比雷达图

    #mermaid-svg-8iZ30Gk0WicpngJA{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8iZ30Gk0WicpngJA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8iZ30Gk0WicpngJA .error-icon{fill:#552222;}#mermaid-svg-8iZ30Gk0WicpngJA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8iZ30Gk0WicpngJA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8iZ30Gk0WicpngJA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8iZ30Gk0WicpngJA .marker.cross{stroke:#333333;}#mermaid-svg-8iZ30Gk0WicpngJA svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8iZ30Gk0WicpngJA p{margin:0;}#mermaid-svg-8iZ30Gk0WicpngJA :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    高级玩家专区

    通用领域

    消费电子

    快速原型

    NXP LPC

    STM32F1

    MindMotion

    VeriSilicon

    开发成本低 –> 开发成本高

    灵活性低 –> 灵活性高

    "两种USB IP适用场景"


    第六章:实战经验——移植代码中最容易踩的坑

    💣 坑1:DATA0/DATA1同步

    VeriSilicon硬件自动管理toggle,MindMotion需要软件维护ep_data_n。

    移植代码中的修补:

    // SETUP之后必须强制重置DATA toggle为DATA1
    if (token == USB_TokenPid_SETUP) {
    ep_data_n[0][USB_Direction_OUT] = 1;
    ep_data_n[0][USB_Direction_IN] = 1; // 注释:修复了原版遗漏!
    }

    💣 坑2:SET_ADDRESS的延迟生效

    USB协议规定:设备在收到SET_ADDRESS请求后,必须在STATUS阶段的ZLP发送完成后才切换地址。

    MindMotion需要手动处理:

    if ((size == 0) && (usb_pending_addr != 0)) {
    USB_SetDeviceAddr(USB, usb_pending_addr); // 在IN完成后才设置地址
    usb_pending_addr = 0;
    }

    💣 坑3:双缓冲残留数据

    BDT的even/odd双缓冲机制在连续快速传输时,容易把旧数据误发出去。

    移植代码的防御:

    // 每次IN完成后,立即清除另一个空闲BDT的OWN位
    usb_bd_tbl.Table[0][USB_Direction_IN][ep_next_odd[0][USB_Direction_IN]].OWN = 0;

    💣 坑4:总线复位后的状态恢复

    VeriSilicon的硬件复位会自动重置所有状态,MindMotion的BDT在复位后需要软件重新初始化。

    移植代码的处理:

    static void usb_bus_reset_process(void) {
    // 清空所有BDT
    for (i=0; i<...; i++) {
    usb_bd_tbl.Index[i].HEAD = 0;
    }
    // 重置软件状态
    ep0_tx_busy = 0;
    usb_state = USB_STATE_DEFAULT;
    // 重新使能端点
    USB_EnableEndPoint(USB, 0, USB_EndPointMode_Control, true);
    // 预提交EP0 OUT接收
    usb_ep0_out_receive();
    }


    第七章:终极总结——两张架构的“择偶指南”

    如果你…选VeriSilicon选MindMotion BDT
    是应用工程师,只想快速实现USB功能 ✅ 最佳选择 ❌ 需要吃透协议
    需要复合设备(键盘+鼠标+存储一体) ⚠️ 受限于硬件状态机 ✅ 灵活配置每个端点
    芯片面积和成本敏感 ❌ 硬件开销大 ✅ 逻辑少,面积小
    希望中断处理简单 ✅ 丰富的独立中断 ❌ 单一TOKDONE,需软件分发
    需要高速批量传输(U盘、摄像头) ⚠️ FIFO模式CPU负担重 ✅ DMA模式更高效
    团队有USB协议专家 ⚠️ 专家技能浪费 ✅ 专家能发挥极致灵活

    一句话总结:VeriSilicon的IP把复杂性留给自己(硬件),把简单留给开发者;MindMotion的BDT把复杂性留给开发者(软件),把灵活性和低成本留给芯片。二者没有绝对优劣,只有适用场景的区别。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 解剖USB控制器移植:从VeriSilicon到MindMotion的“外科手术式”改造
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!