资讯动态

Marlin DUE USB 栈溯源与定制:Atmel ASF 代码的竞态修复与升级维护指南

发布时间:2026/9/13 15:35:34 来源:尧图企业网站定制
Marlin DUE USB 栈溯源与定制Atmel ASF 代码的竞态修复与升级维护指南【免费下载链接】MarlinMarlin is a firmware for RepRap 3D printers optimized for both 8 and 32 bit microcontrollers. Marlin supports all common platforms. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.项目地址: https://gitcode.com/GitHub_Trending/ma/Marlin导读本文以 Marlin/src/HAL/DUE/usb/README.md 为核心系统梳理 Marlin 固件在 Arduino DueSAM3X8EHAL 目录DUE上 USB 子系统的完整来龙去脉这部分代码源自 Atmel ASFAdvanced Software FrameworkMarlin 在引入后针对 UOTGHS 设备驱动做了哪些关键竞态条件修复、如何通过conf_usb.h将 CDC 与 MSC 组合成复合设备以及升级 ASF 时需要注意的结构性障碍。读完本文你将掌握该 USB 目录内每个文件的职责、Marlin 对上游代码的全部本地修改点及其背后的嵌入式时序原理并能为后续维护或移植该 USB 栈提供可直接落地的检查清单。一、背景DUE HAL 与 USB 栈的引入Marlin 的 DUE 支持位于 Marlin/src/HAL/DUE对应的主控芯片为 Atmel/Microchip SAM3X8ECortex-M3。SAM3X8E 内置 USB On-The-Go 高速端口控制器UOTGHSMarlin 利用它实现两类关键能力USB CDC虚拟串口作为 MarlinSerialUSB.cpp 的底层通道让主机通过 USB 直接与固件通信G-code 收发、状态监控USB MSC大容量存储当启用HAS_MEDIA如 usb_flashdrive时将 SD 卡以 USB 移动存储方式暴露给主机。README 明确指出Marlin 中的 USB 文件并非自行编写而是从 Atmel ASF 获取后移植进仓库。ASF 是 Atmel/Microchip 提供的嵌入式软件框架提供了大量现成的 USB 设备类驱动与示例Marlin 正是基于其中的 composite复合设备示例构建了自己的 USB 栈。二、USB 目录结构与文件职责当前仓库中该子系统位于 Marlin/src/HAL/DUE/usb共 40 个文件可按职责分为几组分组文件职责设备控制器UDCudc.c/udc.h/udd.hUSB 设备栈核心管理枚举、标准请求、设备状态机设备驱动UOTGHSuotghs_device_due.c/uotghs_device_due.h/uotghs_otg.h针对 SAM3X/SAM3A 的 UOTGHS 底层寄存器驱动README 中提到的竞态修复即在此文件类驱动UDIudi_cdc.c/.h、udi_msc.c/.h、udi_composite_desc.c、udi_cdc_desc.cCDC 通信类与 MSC 存储类的协议实现及描述符定义配置与协议头conf_usb.h、conf_access.h、usb_protocol.h、usb_protocol_cdc.h、usb_protocol_msc.h、udi_cdc_conf.h设备级配置、USB 协议结构体定义平台时钟/编译器辅助sysclk.c/.h、pll.h、osc.h、genclk.h、compiler.h、preprocessor.h、stringz.h、tpaste.h、mrepeat.h时钟使能、宏展开等 ASF 基础设施存储访问sd_mmc_spi_mem.cpp/.h、ctrl_access.c/.h、sbc_protocol.h、spc_protocol.hMSC 后端与 SD/MMC 介质访问应用胶水层usb_task.c/.hMarlin 与 USB 栈之间的回调实现见第五节其他arduino_due_x.hArduino Due 平台相关的板级定义从结构看这是典型的ASF composite 设备布局设备驱动UDD在上、类驱动UDI居中、应用回调usb_task_*在最上层面向 Marlin 业务。三、来源考证ASF 与版本时间线README 提供了两个关键事实获取途径Atmel 并不以源码仓库形式发布这些文件需要从 ASFAdvanced Software Framework包中提取。README 中给出了 ASF 的官方下载入口Microchip 官网的 Advanced Software Framework 页面Marlin 从中抽取 USB 相关文件放入DUE/usb。版本推断Marlin 维护者并不掌握所采用 ASF 的确切版本号唯一可依赖的证据是文件头部的版权声明——仓库内几乎所有 USB 文件如uotghs_device_due.c、conf_usb.h、usb_task.c都标注Copyright (c) 2011–2015 Atmel Corporation由此推断源码基线对应 2015 年左右的 ASF 版本。这一“无版本号、仅版权时间”的状况正是后续升级困难见第六节的根源之一。四、核心修改uotghs_device_due.c 的竞态条件修复README 强调这些文件“大部分未经修改仅存在轻微外观改动”但有一处意义重大的修改即修改了uotghs_device_due.c以解决在冻结外设时钟时可能使中断保持置位asserted的竞态条件该竞态会因中断风暴interrupt storm导致系统挂起与看门狗复位。结合 uotghs_device_due.c 中的// Marlin modification:注释可以还原出一组成体系的修复而不仅是单点改动4.1 修改一时钟冻结宏加入内存屏障otg_freeze_clock()/otg_unfreeze_clock()是控制 UOTGHS 外设时钟开关的核心宏。Marlin 先#undef掉 ASF 原始定义再重新定义在冻结/解冻操作前后插入 ARM 的__DSB()数据同步屏障// Marlin modification: Redefine the otg_freeze_clock and otg_unfreeze_clock macros // to add memory barriers to ensure that any accesses to USB registers arent re-ordered // to occur while the clock is frozen. #undef otg_freeze_clock #undef otg_unfreeze_clock #define otg_freeze_clock() do { \ __DSB(); \ Set_bits(UOTGHS-UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK); \ } while (0) #define otg_unfreeze_clock() \ do { \ Clr_bits(UOTGHS-UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK); \ __DSB(); \ } while (0)原理Cortex-M3 处理器会对内存访问进行重排序。若在设置UOTGHS_CTRL.FRZCLK冻结时钟位之前前面对 USB 寄存器的写操作尚未真正到达外设总线那么这些访问可能“迟到”——在时钟已被冻结后才抵达寄存器导致中断标志位被意外置起且无法清除。插入__DSB()可强制此前所有内存/外设访问完成杜绝这种乱序窗口。4.2 修改二RESET/SOF/MSOF 中断使能时机后移原 ASF 实现中USB 的 RESET、SOF、MSOF 三个同步中断在udd_attach()里使能。Marlin 的注释明确指出这存在竞态这些中断可能在时钟被冻结时被触发且无法清除。修复方式是双管齐下在udd_attach()中改为显式禁用这三个中断通过新增的disable_and_ack_sync_interrupts()确保它们在时钟冻结前不会被置位将三个中断的使能推迟到 wake-up 中断处理函数中、otg_unfreeze_clock()已经执行之后见 uotghs_device_due.c// Marlin modification: The RESET, SOF, and MSOF interrupts were previously // enabled in udd_attach, which caused a race condition where they could // be raised and unclearable with the clock is frozen. They are now // enabled here, after the clock has been unfrozen in response to the wake // interrupt. udd_enable_reset_interrupt(); udd_enable_sof_interrupt(); #ifdef USB_DEVICE_HS_SUPPORT udd_enable_msof_interrupt(); #endif这样从时序上保证了中断只有在 USB 时钟可用已解冻之后才会被使能从根源上消除了“时钟冻结 中断置位”的交错窗口。4.3 修改三新增 disable_and_ack_sync_interrupts() 辅助函数为解决“禁用与清除中断之间缺少内存屏障导致时钟冻结后中断仍保持置位”的问题Marlin 新增了静态辅助函数统一所有禁用同步中断的路径uotghs_device_due.cstatic void disable_and_ack_sync_interrupts() { // Disable USB line events udd_disable_reset_interrupt(); udd_disable_sof_interrupt(); #ifdef USB_DEVICE_HS_SUPPORT udd_disable_msof_interrupt(); #endif __DSB(); udd_ack_reset(); udd_ack_sof(); #ifdef USB_DEVICE_HS_SUPPORT udd_ack_msof(); #endif __DSB(); }其要点在于先禁能、再__DSB()、再清除中断标志、再__DSB()。两个屏障分别确保“禁能已完成”和“清除已完成”使后续冻结时钟时不存在悬空的中断源。4.4 修改四udd_detach() 中的显式中断禁用在udd_detach()设备从总线断开路径中Marlin 同样调用disable_and_ack_sync_interrupts()注释说明这是为了保证时钟冻结之后不再有 RESET/SOF/MSOF 中断被触发uotghs_device_due.c。这与修改二形成对称的“挂接前禁、断开前也禁”策略。4.5 修改五端点 in_send 中断的屏障在端点发送完成处理中Marlin 还追加了一处__DSB()屏障。注释坦承这是防御性修复“这不是观察到的问题但其他中断在缺少该屏障时出现过异常行为”uotghs_device_due.c。它体现了 Marlin 团队在修复竞态时形成的统一规范凡是“禁能—清除”序列都补齐内存屏障。4.6 修复效果小结修改点目的对应代码位置冻结/解冻宏 __DSB()防止寄存器访问乱序到冻结窗口内uotghs_device_due.cRESET/SOF/MSOF 使能后移避免中断在时钟冻结时被置位uotghs_device_due.cdisable_and_ack_sync_interrupts()统一带屏障的禁能清除序列uotghs_device_due.cdetach 路径显式禁用同步中断断开后不再有悬空中断uotghs_device_due.cin_send 屏障防御性修复规范禁能/清除顺序uotghs_device_due.c这些修复共同保证了 DUE 平台在 USB 挂起/唤醒、插入/拔出等极端时序下不会出现 README 所述的“挂起 看门狗复位”故障。五、配置与应用的定制层除驱动层竞态修复外Marlin 还在配置与应用两层对 ASF 代码做了针对性定制。5.1 conf_usb.h复合设备CDC MSC配置conf_usb.h 是 Marlin 定制 USB 行为的主要入口关键配置如下//! Device definition (mandatory) #define USB_DEVICE_MAJOR_VERSION 1 #define USB_DEVICE_MINOR_VERSION 0 #define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA) #define USB_DEVICE_ATTR \ (USB_CONFIG_ATTR_SELF_POWERED) //! Control endpoint size #define USB_DEVICE_EP_CTRL_SIZE 64 //! Two interfaces for this device (CDC COM CDC DATA MSC) #define USB_DEVICE_NB_INTERFACE 3 //! 5 endpoints used by CDC and MSC interfaces #define USB_DEVICE_MAX_EP 5值得注意的设计细节条件编译驱动#if HAS_MEDIA分支启用 MSC 与 composite 描述符UDI_COMPOSITE_DESC_T等否则退化为纯 CDC 设备仅包含udi_cdc_conf.h。这意味着是否挂载 USB 存储完全由 Marlin 配置宏HAS_MEDIA决定无需改动 ASF 驱动本体。高速模式下的 DPRAM 预算代码注释说明了在 HS 模式下 bulk 端点每端点 512 字节CDC 与 MSC 共 4 个 bulk 端点需 4KB DPRAM空间紧张因此通过UDD_BULK_NB_BANK(ep)将 CDC 的 bulk 端点降为单 bank((ep 4 || ep 5) ? 1 : 2)保留 MSC 双 bank 以维持存储性能。这是 ASF 官方示例自带的权衡逻辑Marlin 完整继承。MSC 身份标识UDI_MSC_GLOBAL_VENDOR_ID定义为M,A,R,L,I,N,3,D即 “MARLIN3D”产品版本1,.,0,0——主机端看到的 USB 大容量存储设备厂商名即由此而来。CDC 默认线路参数115200 波特、1 停止位、无校验、8 数据位UDI_CDC_DEFAULT_RATE等与 Marlin 串口默认速率保持一致。头文件包含顺序文件末尾才 includeudi_cdc.h/udi_msc.h注释说明这是为了避免编译错误类驱动头文件依赖此前定义好的端点宏。5.2 usb_task.cMarlin 应用层回调usb_task.c 把 ASF 类驱动的回调接到 Marlin 业务上其中有几处非常“Marlin 化”的实现MSC 处理期间喂狗usb_task_idle()在处理 SD 卡 USB 访问的循环中持续重置看门狗REG_WDT_CR WDT_CR_WDRSTT | WDT_CR_KEY(0xA5)防止长传输触发看门狗复位——这与 README 中“看门狗复位”的话题一脉相承1200 bps Arduino 兼容复位usb_task_cdc_set_dtr()实现了经典的 Arduino bootloader 进入技巧——当主机以 1200 bps 打开端口后关闭DTR 从高变低固件触发initiateReset(250)进入编程模式。代码注释明确写道这是“Arduino-Compatible kludge”usb_task.cMicrosoft WCID 描述符静态构造了“3D Printer compatible descriptor”microsoft_compatible_id_descriptor用于 Windows 识别设备类型并自动配置为 3D 打印机状态跟踪usb_task_cdc_dtr_active()等查询函数供上层如 MarlinSerialUSB.cpp判断主机串口是否真正打开。六、版本信息与升级考量README 对版本与升级给出了明确的评估结论这是本目录未来维护的重要决策依据当前基线不确定所移植 ASF 的确切版本仅能依据文件头版权声明判断源码来自约 2015 年的 ASF。升级评估Marlin 维护者考察过ASF 3.52.02022 年发布中的对应文件结论是没有发现足以立即升级的收益因此维持现有基线。最大障碍——目录结构不一致README 特别强调Marlin 中的文件布局与 ASF 原始目录结构并不一致这使“逐文件比对、应用更新”变得困难且易错。由此 README 给出两条维护建议升级时逐文件仔细比对确保 Marlin 本地修复尤其第四节中的竞态修复不会被上游文件覆盖丢失让 Marlin 目录结构与 ASF 对齐或至少为每个文件记录其 ASF 来源以便未来能机械化地完成升级比对。七、给维护者与移植者的检查清单基于上述分析无论你是要维护 DUE 平台、还是将这套 USB 栈移植到其他 SAM 芯片建议核对以下事项保留所有// Marlin modification:标注仓库中此类注释集中在 uotghs_device_due.c它们是移植/升级时最容易被覆盖的部分验证__DSB()屏障是否齐全凡涉及otg_freeze_clock/otg_unfreeze_clock以及“禁能中断→清除标志”的序列都必须有数据同步屏障确认中断使能时序RESET/SOF/MSOF 中断只能在otg_unfreeze_clock()之后使能不能在udd_attach()中提前打开核对HAS_MEDIA分支启用 USB 存储时确认conf_usb.h的端点数量USB_DEVICE_MAX_EP与 DPRAM 预算UDD_BULK_NB_BANK匹配你的芯片升级上游文件时先完成第四节修改点的差异对比再考虑是否引入新版 ASF。结语Marlin/src/HAL/DUE/usb 是一份“高价值、低改动”的第三方代码它让 Marlin 在 SAM3X8E 上零成本获得成熟稳定的 USB 协议栈而 Marlin 团队的贡献集中在用少量精准的内存屏障与中断时序调整消除上游驱动在极端电源/时钟场景下的崩溃隐患。理解这份 README 及其配套源码不仅能解释“为什么这里有一堆看似陌生的 ASF 文件”更能为所有基于 SAM 平台的 Marlin 移植与固件排障提供直接依据。【免费下载链接】MarlinMarlin is a firmware for RepRap 3D printers optimized for both 8 and 32 bit microcontrollers. Marlin supports all common platforms. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.项目地址: https://gitcode.com/GitHub_Trending/ma/Marlin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价