XMODEM协议解析

XMODEM协议

目的

本文主要介绍XMODEM协议,一些常用工具(如SecureCRT、TeraTerm)的具体行为,便于我们用于制作Uart Bootloader.

简介

XMODEM 是一种早期的、经典的串行通信文件传输协议,主要用于通过串口(如RS 232)在2台设备间可靠的传输数据. 于1997年由Ward Christensen提出,现在也常用于嵌入式系统、Bootloader等场景.

特点

XMODEM 核心设计目标:在高误码率、低带宽的串行链路上,实现简单而可靠的数据传输.

主要特点:

  • 简单,容易实现:协议逻辑简单,代码量小
  • 点对点的半双工通信:同一时间只有一方能发送数据
  • 块(Block)传输:数据被分为固定大小的“块”进行传输
  • 错误校验:使用校验和或CRC校验 模式,确保数据正确性
  • 等待式ARQ:发送方发送一个数据块后,必须等待接收方的确认(ACK),才会发送下一个.

基本流程

XMODEM 采用发送方主动发送、接收方确认的方式(ARQ),流程如下:

  1. 初始化阶段
  • 接收方周期性发送 NAK(校验和模式)或 C(CRC模式)
  • 发送方收到后,开始发送数据
  1. 数据传输阶段
  • 数据被分割为固定大小的数据块(通常128byte,XMODEM-1K扩展协议对应1024byte)
  • 每个数据块发送后,等待接收方确认
  • 校验成功,则应答 ACK;校验失败,则应答 NAK,发送方重传
  1. 结束阶段

所有数据传输结束后,

  • 发送方发送 EOT
  • 接收方应答 ACK
  • 传输结束

数据块格式

XMODEM每个数据块(也称 数据包),格式如下:

+--------+--------+--------+----------------+--------+
|  SOH   |  BLK # | ~BLK # |   Data         | CHECK  |
+--------+--------+--------+----------------+--------+

注意:BLK = Block Number(块序号)

字段 大小(byte) 描述
SOH 1 数据块起始标志.
SOH=0x01,Data长度128byte;
STX=0x02,Data长度1Kbyte
BLK # 1 Block Number(块序号,1~255循环),确保数据(块)按顺序接收
~BLK # 1 块序号的按位取反,用于简单验证序列号是否正确
Data 128/1024 实际的文件数据. 如果不足128/1024 byte,则用CPMEOF(0x1A)或NULL(0x00) 填充
CHECK 1/2 取决于接收方确定的校验模式:
* 校验和模式,1byte,数据区所有字节之和;
* CRC模式,2byte,16位CRC校验

XMODEM-1K协议

对于经典XMODEM协议,数据块起始标志为SOH=0x01;而对于扩展的XMODEM-1K协议,数据块起始标志为STX=0x02.

与XMODEM区别

XMODEM-1K:
XMODEM-1K将XMODEM的Data长度,由128byte 扩展到1024byte. XMODEM-1K 几乎总是配合 CRC 使用,很少再使用校验和.

协商方式(实现)

发送端如何确认接收端是否支持XMODEM-1K呢?如果不支持怎么办?

XMODEM 并没有正式的协商机制,不过工程上通常采用:

  1. 接收端发送'C',请求CRC模式;
  2. 发送端:
    • 优先发送STX(1KB数据块)
    • 如果接收端不支持,应答NAK
  3. 发送端退化为SOH(128B数据块)

这是事实上的标准,而非协议规范.

BLK块序号

BLK 有3个作用:

1)确保数据块按顺序接收

第1个块BLK=0x01,第2个块BLK=0x02,...,依次类推,第255个块BLK=0xFF,第256个块BLK绕回0x01.

如此,接收方可判断接收到的数据块,是否为下一个期望的数据块.

2)检测重复块

当接收方已正确接收到某个块,并ACK;但是发送方未收到ACK(可能丢失),而重复发送数据块.

接收方可据此判断是否为重复块,如果是,则丢弃;如果不是,则正常接收.

3)与~BLK组成简单的一致性检验

~BLKBLK按位取反:

~BLK = BLK ^ 0xFF
<=>
~BLK + BLK = 0xFF
<=>
~BLK = ~(BLK) & 0xFF // 求反

CHECK错误检测

XMODEM支持2种错误检测机制:

1)校验和(Checksum)

CHECK 字段占 1byte,对 128bytes 数据逐字节相加取低 8bits . 原始的XMODEM协议使用该方式,需要接收方发送NAK启动传输.

2)CRC-16(XMODEM-CRC)

CHECK 字段占 2byte,可靠性强于校验和模式. 需要接收方在传输开始前,通过发送字符'C'启动传输.

多项式:0x1021,即生成多项式为:

0x1021 = 0b 0001 0000 0010 0001

按位映射为:

x^16 + x^12 + x^5 + 1

参考实现代码:

/**
 * @brief Calculate CRC16 for input package.
 * 
 * @note CRC-16 XMODEM 
 * polynomial: x^16 + x^12 + x^5 + 1
 * 
 * see https://blog.csdn.net/u012028275/article/details/112067463
 */
uint16_t xmodem_calc_crc(const uint8_t *data, uint32_t length)
{
    uint16_t crc = 0;
    while (length) {
        crc = crc ^ ((uint16_t)*data << 8u);
        length--;
        data++;

        for (uint8_t i = 0; i < 8; i++) {
            if (crc & 0x8000u) {
                crc = (crc << 1) ^ 0x1021u;
            }
            else {
                crc = crc << 1;
            }
        }
    }
    return crc;
}

典型流程

接收方、发送方正常通信的时序图:

接收方 (Receiver)                                发送方 (Sender)
─────────────────                              ─────────────────
        |                                              |
        |  NAK / 'C'     (请求启动传输)                 |
        |--------------------------------------------->|
        |                                              |
        |<-- SOH | BLK | ~BLK | DATA[128] | CRC  ------|
        |                                              |
        |  [本地处理]                                   |
        |  校验 BLK, ~BLK                              |
        |  校验 CRC                                    |
        |                                              |
        |  ACK                                         |
        |--------------------------------------------->|
        |                                              |
        |<-- SOH | BLK+1 | ~(BLK+1) | DATA | CRC ------|
        |                                              |
        |                    ...                       |
        |                                              |
        |<-- EOT --------------------------------------|
        |                                              |
        |  ACK           (传输结束)                     |
        |--------------------------------------------->|

接收方CRC校验失败,发送方重传的时序图:

接收方                                  发送方
──────                                  ──────
   |                                        |
   |<-- SOH | BLK | ~BLK | DATA | CRC ------|
   |                                        |
   |  [本地处理] CRC 校验失败                |
   |                                        |
   |--- NAK ------------------------------->|
   |                                        |
   |<-- SOH | BLK | ~BLK | DATA | CRC ------| 整帧重传
   |                                        |
   |  [本地处理] 校验成功                    |
   |                                        |
   |--- ACK ------------------------------->|

参考

XMODEM 协议介绍和C语言实现
【CRC笔记】CRC-16 XMODEM C语言实现

posted @ 2025-12-21 19:51  明明1109  阅读(0)  评论(0)    收藏  举报