新闻详情

新闻详情

首页 / 资讯中心 / 详情

Marlin 二进制文件传输协议(BFT)实战指南:从 M28 B1 到 SD 卡高速写入

发布时间:2026/9/13 13:03:14来源:尧图网络
Marlin 二进制文件传输协议(BFT)实战指南:从 M28 B1 到 SD 卡高速写入
Marlin 二进制文件传输协议BFT实战指南从 M28 B1 到 SD 卡高速写入【免费下载链接】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 固件仓库中的协议规范文档与源码完整讲解通过串口向 SD 卡进行二进制文件传输的 BFTBinary File Transfer协议。文中将带你掌握协议的数据包格式、Fletchers 校验和算法、连接控制与传输控制两类报文以及从M28 B1进入二进制模式到最终关闭连接的标准交互流程并深入binary_stream.cpp、M28_M29.cpp等源码印证每个协议细节的实现方式。协议概览与启用前提Marlin 通过串口将二进制数据直接写入内部存储SD 卡的能力由编译期选项BINARY_FILE_TRANSFER控制。该选项默认关闭需要在 Marlin/Configuration_adv.h 中取消注释// Add an optimized binary file transfer mode, initiated with M28 B1 //#define BINARY_FILE_TRANSFER #if ENABLED(BINARY_FILE_TRANSFER) // Include extra facilities (e.g., M20 F) supporting firmware upload via BINARY_FILE_TRANSFER //#define CUSTOM_FIRMWARE_UPLOAD #endif启用后配合CUSTOM_FIRMWARE_UPLOAD还可支持固件上传等扩展用途。在 ini/features.ini 中可以确认该功能关联的编译单元BINARY_FILE_TRANSFER build_src_filtersrc/feature/binary_stream.cpp src/libs/heatshrink即启用该选项后固件会额外编译 Marlin/src/feature/binary_stream.cppBFT 协议状态机与文件传输实现以及Marlin/src/libs/heatshrinkheatshrink 解压器用于可选的压缩传输。在真实构建环境中buildroot/tests/mks_robin_nano_v1v2_maple/config-04.ini即为一个同时启用 BFT 的测试配置示例。一旦固件以该选项编译主机端PC 软件等向打印机串口发送 ASCII 命令M28 B1即可进入二进制传输模式。这一入口定义在 Marlin/src/gcode/sd/M28_M29.cpp 中M28解析到以B开头且后跟数字的参数时若数字大于 0 则置位card.flag.binary_mode并回显Switching to Binary Protocol同时记录当前命令所在串口作为transfer_port_index后续二进制数据将从该端口接收。进入二进制模式后Marlin 的串口命令循环不再按 ASCII 行解析而是直接把串口数据喂给BinaryStream::receive()状态机这一点可以从 Marlin/src/gcode/queue.cpp 的实现得到印证当card.flag.binary_mode为真时直接调用binaryStream[card.transfer_port_index.index].receive(...)并以serial_line_buffer作为接收缓冲。字节序Endianness协议中所有多字节数据结构均采用little-endian小端序。构造数据包时低位字节必须先行发送。每个数据包以 16 位起始标记Start Token0xB5AD开头因此线上实际先发送0xAD再发送0xB5。一个只有头部、没有载荷的 Connection SYNC 数据包在字节流中的排列如下S S P P P H t y r a a e a n o c y a r c t k l d t o e o e c t a r o d l t C y l S p e e n ---- -- - - ---- ---- ADB5 00 0 1 0000 0103即AD B5Start Token→00Sync Number→0协议 ID 高位 4bit与1包类型低位 4bit合成meta字节 →00 00Payload Length→01 03Header Checksum。在源码中头部的解析对应 Marlin/src/feature/binary_stream.h 中定义的Header联合体其中meta字节的高 4 位是protocol()、低 4 位是type()。数据包头部Packet Header头部固定为 8 字节布局如下0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ------------------------------------------------------------ | Start Token (0xB5AD) | Sync Number | Prot- | Pack- | | | | ocol | et | | | | ID | Type | ------------------------------------------------------------ | Payload Length | Header Checksum | --------------------------------------------------------------各字段说明字段宽度说明Start Token16 bits每个数据包必须以 16 位值0xB5AD开始。Sync Number8 bits同步值。从同步SYNC之后的每个数据包都应将其递增 1。Protocol ID4 bits协议 ID。0为 Connection Control连接控制1为 Transfer文件传输。详见下文。Packet Type4 bits数据包类型 ID。取值取决于 Protocol ID见下文各节。Payload Length16 bits载荷数据长度。若该值大于 0则头部之后紧跟数据包载荷。Header Checksum16 bits头部数据不含 Start Token的 16 位 Fletchers 校验和。数据包载荷Packet Payload当头部中的 Payload Length 字段非零时头部之后应跟随后续载荷0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -------------------------------------------------------------- | Payload Data ... | -------------------------------------------------------------- | ... | Packet Checksum | --------------------------------------------------------------字段宽度说明Payload DataPayload Length 字节载荷数据。长度不应超过 Connection SYNC 操作报告的缓冲长度。Packet Checksum16 bits头部与载荷的 16 位 Fletchers 校验和包含 Header Checksum但不含 Start Token。从源码看接收端的状态机PACKET_HEADER → PACKET_DATA → PACKET_FOOTER → PACKET_PROCESS会严格校验头部校验和与整包校验和任何一步失败都会进入PACKET_RESEND状态向主机发送rs重传请求Marlin/src/feature/binary_stream.h。Fletchers 校验和无论头部校验和还是整包校验和都使用 16 位 Fletchers 校验和算法且两种情况都不包含数据包前两个字节即 Start Token。一个简单实现示例uint16_t cs 0; for (size_t i 2; ipacket.size(); i) { uint8_t cslow (((cs 0xFF) packet[i]) % 255); cs ((((cs 8) cslow) % 255) 8) | cslow; }在固件侧BinaryStream::checksum()实现了完全相同的迭代公式// fletchers 16 checksum uint32_t checksum(uint32_t cs, uint8_t value) { uint16_t cs_low (((cs 0xFF) value) % 255); return ((((cs 8) cs_low) % 255) 8) | cs_low; }Marlin/src/feature/binary_stream.h。接收时头部校验和会在读到第 6 字节时被暂存因为头部校验和字段本身不能参与自己的计算随后与头部中的校验和字段比对Marlin/src/feature/binary_stream.h。通用响应General Responsesok除 SYNC 数据包外所有数据包都会收到一条okSYNC消息作为确认。该确认仅表示客户端已收到数据包且头部格式良好并不表示操作成功——在客户端还会发送详细响应消息的情况下ok不代表业务成功。当前实现中最值得注意的是当主机发送多个相同 Sync Number 的数据包时客户端仍会回复ok但不会发送正确的业务响应或任何错误信息。注意ok确认会在任何数据包类型专属输出之前发送。SYNC值应与最后发送数据包的 Sync Number 一致下一个数据包应使用该值 1 的 Sync Number。示例ok1从源码看ok是在PACKET_PROCESS状态处理业务前先输出的Marlin/src/feature/binary_stream.hcase StreamState::PACKET_PROCESS: sync; packet_retries 0; bytes_received packet.header.size; SERIAL_ECHOLNPGM(ok, packet.header.sync); // transmit valid packet received dispatch();rs当数据包乱序到达Sync Number 不是上一个 Sync Number 1时客户端会发送一条rsSYNC消息其中携带最后接收到的 Sync Number提示主机据此重传。示例rs1源码中的触发场景包括头部校验和损坏、载荷校验和损坏、数据流超时等此时状态机进入PACKET_RESEND并输出rsMarlin/src/feature/binary_stream.h。另外若主机的 Sync Number 恰好是上一个已确认包的 Sync即sync - 1客户端会判定此前的ok应答可能丢失于是补发ok并丢弃重复载荷Marlin/src/feature/binary_stream.h。连接控制Connection ControlProtocol ID 0Protocol ID 0 的数据包负责控制二进制连接本身只有 2 种类型Packet Type名称说明1SYNC同步主机与客户端并获取连接信息。2CLOSE关闭二进制连接并切回 ASCII 模式。SYNC 数据包SYNC 数据包应为主机在启用二进制模式后发送的第一个数据包。成功后客户端会发送 sync 响应。注意这是唯一一个不会被ok响应的数据包。返回的 sync 响应格式ssSYNC,BUFFER_SIZE,VERSION_MAJOR.VERSION_MINOR.VERSION_PATCH值说明SYNC当前 Sync Number应作为下一个数据包的 Sync Number并在其后每个数据包上递增 1。BUFFER_SIZE客户端缓冲区大小。数据包 Payload Length 不得超过该值。VERSION_MAJOR客户端 Marlin BFT 协议主版本号例如0。VERSION_MINOR客户端 Marlin BFT 协议次版本号例如1。VERSION_PATCH客户端 Marlin BFT 协议补丁版本号例如0。示例响应ss0,96,0.1.0源码中SYNC 数据包被特殊处理它在头部校验通过后立即响应且不经过 Sync Number 校验Marlin/src/feature/binary_stream.h// The SYNC control packet is a special case in that it doesnt require the stream sync to be correct if (static_castProtocol(packet.header.protocol()) Protocol::CONTROL static_castProtocolControl(packet.header.type()) ProtocolControl::SYNC) { SERIAL_ECHOLN(F(ss), sync, C(,), buffer_size, C(,), version_major, C(.), version_minor, C(.), version_patch); stream_state StreamState::PACKET_RESET; break; }示例响应中的96即为buffer_size对应 Marlin/src/feature/binary_stream.h 附近的buffer_size常量实际可用的接收缓冲为serial_line_buffer其大小由MAX_CMD_SIZE决定见 Marlin/src/gcode/queue.cpp 注释。CLOSE 数据包CLOSE 数据包应为主机发送的最后一个数据包。成功后客户端切回 ASCII 模式。源码中的实现非常直接——将card.flag.binary_mode置为 falseMarlin/src/feature/binary_stream.hcase ProtocolControl::CLOSE: // revert back to ASCII mode card.flag.binary_mode false; break;传输控制Transfer ControlProtocol ID 1Protocol ID 1 的数据包控制连接上的文件传输Packet Type名称说明0QUERY查询客户端协议细节与压缩参数。1OPEN打开文件用于写入并开始接收待传输数据。2CLOSE结束写入并关闭当前文件。3WRITE向已打开文件写入数据。4ABORT中止文件传输。这些类型的解析与分发由SDFileTransferProtocol::process()完成Marlin/src/feature/binary_stream.h各分支与上表一一对应。QUERY 数据包QUERY 数据包应为主机在 SYNC 数据包之后发送的第二个数据包。成功后除oksync确认外还会返回 query 响应。返回的 query 响应格式PFT:version:VERSION_MAJOR.VERSION_MINOR.VERSION_PATCH:compression:COMPRESSION_ALGO(,COMPRESSION_PARAMS)值说明VERSION_MAJOR客户端 Marlin BFT 协议主版本号例如0。VERSION_MINOR客户端 Marlin BFT 协议次版本号例如1。VERSION_PATCH客户端 Marlin BFT 协议补丁版本号例如0。COMPRESSION_ALGO压缩算法。当前为heatshrink或none。COMPRESSION_PARAMS压缩参数以逗号分隔。当前若算法为 heatshrink则为窗口大小window size与前瞻大小lookahead size。示例响应PFT:version:0.1.0:compression:heatshrink,8,4其中heatshrink,8,4的8与4对应 Marlin/src/libs/heatshrink/heatshrink_config.h 中的编译期常量#define HEATSHRINK_STATIC_WINDOW_BITS 8 #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4客户端实现Marlin/src/feature/binary_stream.h会按是否启用BINARY_STREAM_COMPRESSION分别输出 heatshrink 参数或nonecase FileTransfer::QUERY: SERIAL_ECHO(F(PFT:version:), version_major, C(.), version_minor, C(.), version_patch); #if ENABLED(BINARY_STREAM_COMPRESSION) SERIAL_ECHOLN(F(:compression:heatshrink,), HEATSHRINK_STATIC_WINDOW_BITS, C(,), HEATSHRINK_STATIC_LOOKAHEAD_BITS); #else SERIAL_ECHOLNPGM(:compression:none); #endif break;BINARY_STREAM_COMPRESSION在 Marlin/src/feature/binary_stream.h 中定义并随BINARY_FILE_TRANSFER一同启用 heatshrink 解码器同时为 DMA 传输准备了 512 字节、按sizeof(size_t)对齐的解码缓冲区。OPEN 数据包打开一个文件用于写入。文件名与其他选项在数据包载荷中指定。若固件编译时支持长文件名则文件名可以是长文件名但整个数据包载荷长度不得超过 SYNC 数据包返回的缓冲长度。文件名值必须包含空终止符NULL 字节。载荷布局0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ------------------------------------------------------------- | Dummy | Compression | Filename | ---------------------------------------------------------------| | ... | -------------------------------------------------------------- | ... | NULL (0x0) | Packet Checksum | --------------------------------------------------------------字段宽度说明Dummy8 bits布尔值指示本次文件传输是否真正执行。若为1客户端将假装文件已打开并接受数据传输但实际上不写入任何数据。Compression8 bits布尔值指示待传输数据是否使用 QUERY 数据包返回的算法与参数进行压缩。Filename...包含空终止符字节的文件名。Packet Checksum16 bits头部与载荷的 16 位 Fletchers 校验和包含 Header Checksum但不含 Start Token。响应响应说明PFT:success文件已打开可开始写入。PFT:fail客户端无法打开文件。PFT:busy文件已经处于打开状态。源码中 OPEN 的解析对应Packet::Open结构Marlin/src/feature/binary_stream.hDummy与Compression各占 1 字节各取低 1 位判断布尔值其后为以\0结尾的可变长文件名validate()校验载荷长度并确保末尾是\0。业务逻辑上若已有传输在进行则回PFT:busy校验或打开失败则回PFT:failMarlin/src/feature/binary_stream.h。真正打开文件时调用card.openFileWrite(filename)Marlin/src/feature/binary_stream.h。CLOSE 数据包关闭当前打开的文件。响应响应说明PFT:success缓冲已刷新且文件已关闭。PFT:ioerror客户端存储设备故障。PFT:invalid没有已打开的文件。实现上file_close()会先刷新压缩解码缓冲中残留的数据若启用压缩再调用card.closefile()与card.release()Marlin/src/feature/binary_stream.h。WRITE 数据包向当前打开的文件写入载荷数据。若文件以 Compression 为 1 打开则数据会先解压再写入。载荷长度不得超过 SYNC 数据包返回的缓冲大小。响应成功后返回okSYNC响应。出错时okSYNC响应后还会跟一条错误响应响应说明PFT:ioerror客户端存储设备故障。PFT:invalid没有已打开的文件。从源码看WRITE 分支在没有打开文件时立即回PFT:invalid写入失败如card.write()返回负值时回PFT:ioerrorMarlin/src/feature/binary_stream.h。启用压缩时file_write()将数据送入 heatshrink 解码器并在解码缓冲攒满 512 字节后一次性写入 SD 卡兼顾吞吐与 DMA 对齐要求Marlin/src/feature/binary_stream.h。ABORT 数据包关闭当前打开的文件并将其删除。响应响应说明PFT:success传输已中止文件已删除。实现上transfer_abort()依次调用card.closefile()、card.removeFile(card.filename)、card.release()并重置传输状态Marlin/src/feature/binary_stream.h。此外固件还实现了传输看门狗若传输过程中途中断且超过超时时间默认 10 秒见timeout 10000SDFileTransferProtocol::idle()会自动执行中止逻辑避免 SD 卡上残留处于打开状态的文件Marlin/src/feature/binary_stream.h。典型使用流程完整的二进制文件传输流程共 8 步发送 ASCII 命令M28 B1进入 Binary Transfer 模式。发送 Connection SYNC 数据包记录 Sync Number 与 Buffer Size。发送 Transfer QUERY 数据包使用上一步得到的 Sync Number记录压缩算法与参数。发送 Transfer OPEN 数据包使用「最后 Sync Number 1」携带文件名与压缩选项。若出错发送 Connection CLOSE 数据包并中止。发送 Transfer WRITE 数据包使用「最后 Sync Number 1」携带文件数据。载荷长度不得超过第 2 步报告的 Buffer Size。出错时先发送 Transfer ABORT 数据包再发送 Connection CLOSE 数据包然后中止传输。发送 Transfer CLOSE 数据包使用「最后 Sync Number 1」。发送 Connection CLOSE 数据包使用「最后 Sync Number 1」。客户端此时已回到 ASCII 模式传输完成。一个基于示例响应的简化报文序列示意SYNC0 起步每包递增步骤数据包协议/类型Sync载荷要点期望响应1无ASCII——M28 B1Switching to Binary Protocol2SYNC0/10无ss0,96,0.1.03QUERY1/01无ok1PFT:version:0.1.0:compression:heatshrink,8,44OPEN1/12Dummy0, Compression1, 文件名\0ok2PFT:success5WRITE × N1/33,4,5,…压缩后文件数据≤ Buffer Sizeok3、ok4、…6CLOSE1/26无ok6PFT:success7CLOSE0/27无ok7随后切回 ASCII与主机工具对接的注意事项缓冲上限每个 WRITE 包的载荷长度上限由 SYNC 响应中的BUFFER_SIZE决定示例中为 96 字节实际以固件serial_line_buffer/MAX_CMD_SIZE为准。发送端应按此值切分文件数据超出会导致接收端报Datastream packet data buffer overrunMarlin/src/feature/binary_stream.h。乱序与重传任何rsSYNC响应都意味着主机需要从SYNC指示的位置重新发送头部/载荷校验失败、数据流超时packet_max_wait 500ms见 Marlin/src/feature/binary_stream.h都会触发重传。压缩可选QUERY 响应的heatshrink,8,4表明压缩窗口为 8 位、前瞻为 4 位。若主机端实现压缩须使用与固件一致的参数且在 OPEN 时置 Compression1否则以未压缩明文传输置 Compression0。Dummy 传输OPEN 中 Dummy1 可用于传输演练/压力测试——客户端照常应答并接收数据但不会写 SD 卡Marlin/src/feature/binary_stream.h。能力查询主机可通过M115响应中的BINARY_FILE_TRANSFER能力标识Marlin/src/gcode/host/M115.cpp判断固件是否启用本协议再决定是否发起M28 B1。【免费下载链接】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),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

RAP开发实战:CDS + Fiori Elements实现主明细显示 2026/9/13 13:45:16

RAP开发实战:CDS + Fiori Elements实现主明细显示

做SAP S/4HANA扩展开发的人应该都碰到过这种需求:业务方拿着一张纸质单据过来,说“我要在这个页面上,上面显示抬头信息,下面能够维护明细行,还能增删改”。以前遇到这种主明细(Master-Detail)场…

阅读更多 →
警惕GPT-6等虚假AI模型热词:识别技术谣言与信息陷阱 2026/9/13 13:45:16

警惕GPT-6等虚假AI模型热词:识别技术谣言与信息陷阱

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
深入解读 OpenSEO v0.0.3:Backlinks 反链分析页面上线、品牌改名与 Docker 自托管更新指南 2026/9/13 13:45:16

深入解读 OpenSEO v0.0.3:Backlinks 反链分析页面上线、品牌改名与 Docker 自托管更新指南

深入解读 OpenSEO v0.0.3:Backlinks 反链分析页面上线、品牌改名与 Docker 自托管更新指南 【免费下载链接】open-seo Open source alternative to Semrush and Ahrefs 项目地址: https://gitcode.com/GitHub_Trending/op/open-seo 本篇文章以开源 SEO 工具 …

阅读更多 →
Cilium on K3s 安装指南:从零搭建基于 eBPF 的高可用 Kubernetes 集群 2026/9/13 13:45:16

Cilium on K3s 安装指南:从零搭建基于 eBPF 的高可用 Kubernetes 集群

Cilium on K3s 安装指南:从零搭建基于 eBPF 的高可用 Kubernetes 集群 【免费下载链接】cilium eBPF-based Networking, Security, and Observability 项目地址: https://gitcode.com/GitHub_Trending/ci/cilium K3s 是一款面向生产环境设计的高可用、经认证…

阅读更多 →
AI Agent记忆系统实战:从短期记忆到长期记忆的完整构建方案 2026/9/13 13:45:16

AI Agent记忆系统实战:从短期记忆到长期记忆的完整构建方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Arduino-ESP32 SPI 多总线编程指南:从 SPIClass 双总线示例到硬件底层实现 2026/9/13 13:42:16

Arduino-ESP32 SPI 多总线编程指南:从 SPIClass 双总线示例到硬件底层实现

Arduino-ESP32 SPI 多总线编程指南:从 SPIClass 双总线示例到硬件底层实现 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 本指南以 ESP32 Arduino Core 官方 …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞