Ymodem协议是一种基于Xmodem改进的串行通信文件传输协议,诞生于1980年代,由Ward Christiansen或Chuck Forsberg开发(不同资料记载有差异)。它通过优化数据块大小、引入批处理和强校验机制,显著提升了传输效率和可靠性,广泛应用于嵌入式系统固件升级、工业设备配置等场景。
一、协议核心特点
高效传输
支持1024字节/块的数据包(Xmodem仅128字节),减少协议开销,提升吞吐量。
批处理模式可连续传输多个文件,无需重复握手。
强错误检测
采用16位CRC校验(Xmodem为8位校验和),可检测多位错误(如突发错误)。
接收方通过校验数据包序号与补码关系(如01H与FEH互为补码)验证数据完整性。
public class Crc16Ccitt
{
const ushort poly = 0x1021;
ushort[] table = new ushort[256];
ushort initialValue = 0;
public ushort ComputeChecksum(byte[] bytes)
{
ushort crc = this.initialValue;
for (int i = 0; i < bytes.Length; ++i)
{
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes)
{
ushort crc = ComputeChecksum(bytes);
return new byte[] { (byte)(crc >> 8), (byte)(crc & 0x00ff) };
}
public Crc16Ccitt(InitialCrcValue initialValue)
{
this.initialValue = (ushort)initialValue;
ushort temp, a;
for (int i = 0; i < table.Length; ++i)
{
temp = 0;
a = (ushort)(i << 8);
for (int j = 0; j < 8; ++j)
{
if (((temp ^ a) & 0x8000) != 0)
{
temp = (ushort)((temp << 1) ^ poly);
}
else
{
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}
流控制机制
ACK/NAK响应机制:接收方校验成功后回复ACK(0x06),失败则回复NAK(0x15)触发重传。
超时重传:发送方未收到响应时自动重发数据包。
元数据支持
起始帧包含文件名、文件大小(补零至128字节),便于接收方预分配资源。
二、协议通信流程
Ymodem传输分为三个阶段,以接收方主动发起为特点:
初始化阶段
接收方发送字符'C'(ASCII 0x43)开启传输。
发送方回复起始帧:
| SOH(0x01) | 00H | FFH | 文件名+文件大小+补零 | 16位CRC校验码 |
接收方校验后回复ACK,并再次发送'C'进入数据传输。
数据传输阶段
数据包结构:
| 包头(STX/SOH) | 序号 | 序号补码 | 数据(128/1024B) | CRC校验码 |
STX(0x02)标识1024字节包,SOH(0x01)标识128字节包(仅用于末尾不足1024B时)。
序号从01H开始递增,补码为FEH、FDH等。
接收方校验序号、补码和CRC,成功则回复ACK,失败则NAK请求重发。
结束阶段
发送方发送EOT(0x04)结束传输,接收方首次回复NAK二次确认,二次回复ACK。
若无后续文件,发送方发送全零结束帧:
| SOH | 00H | FFH | 128字节0x00 | CRC校验码 |
接收方回复ACK后终止会话。
三、关键技术实现
数据包结构详解
帧头:用于表示数据帧的长度,主要是信息块长度不同。
包序号:数据包序号只有1字节,范围是0~255;对于数据包大于255的,序号归零重复计算。
帧长度:以SOH (0x01)开始的数据包,信息块是128字节,总长度为133字节;以STX (0x02)开始的数据包,信息块是1024字节,总长度为1029字节。
校验:Ymodem采用CRC16校验算法,校验值为2字节,传输时CRC高八位在前,低八位在后。
字段 | 长度 | 说明 |
---|---|---|
Start Header | 1字节 | SOH (128B)或STX (1024B)标识包类型 |
Packet Number | 1字节 | 数据包序号(从00H起始帧开始,01H为第一包数据) |
Complement | 1字节 | 序号的按位取反(如01H 对应FEH ) |
Data | 可变 | 文件名(起始帧)或文件数据(数据帧),不足时补0x1A 或0x00 |
CRC-16 | 2字节 | 校验范围:包头后所有数据(不含包头) |
错误恢复策略
连续收到NAK或超时:重发数据包,超过阈值则终止传输。
序号不连续:接收方发送NAK要求重传缺失包。
四、与其他协议对比
特性 |
Xmodem |
Ymodem |
Zmodem |
数据块大小 |
128字节 |
128B/1024B |
滑动窗口(动态) |
校验方式 |
8位校验和 |
16位CRC |
32位CRC |
批处理 |
不支持 |
支持 |
支持 |
断点续传 |
不支持 |
不支持 |
支持 |
适用场景 |
小文件低速环境 |
中等文件、可靠性要求 |
大文件高速环境 |
总结
Ymodem协议凭借其1024字节块+批处理+强CRC校验的组合,在串行通信时代实现了效率与可靠性的平衡。尽管逐渐被Zmodem和现代协议取代,其在嵌入式领域仍不可替代。开发时需注意其无加密、流控简单的局限,并合理选择数据块大小以优化传输性能。