STM32 Ymodem 协议及代码解析

文章导图:

ymodem securecrt ymodem securecrt eta_ymodem securecrt

1. Ymodem 协议传输效果

1.1 发送端软件效果图
  • SecureCRT 软件:SecureCRT 支持 Ymodem 协议传输,可以作为接收端也可以作为发送端,这里我们作为发送端发送升级固件给 STM32 接收端。

ymodem securecrt ymodem securecrt eta_Ymodem_02

  • 自制发送端软件:这个是我用 PyQt5 制作的 STM32 IAP 升级软件,作为 Ymodem 发送端发送升级固件给 STM32 接收端。

ymodem securecrt ymodem securecrt eta_ymodem securecrt_03

1.2 STM32接收端效果图

STM32 作为 Ymodem 接收端接收升级固件进行升级。

ymodem securecrt ymodem securecrt eta_STM32_04

2. Ymodem 协议介绍

  YModem 协议是由 XModem 协议演变而来的,每包数据可以达到 1024 字节,是一个非常高效的文件传输协议。我们平常所说的 Ymodem 协议是指的 Ymodem-1K,除此还有 Ymodem-g(没有 CRC 校验,不常用)。YModem-1K 协议用 1024 字节数据帧传输取代了标准的 128 字节数据帧传输,发送的数据会使用 CRC 校验,保证数据传输的正确性。它每传输一个信息块时,就会等待接收端返回 ACK 信号,接收到响应信号后,才会继续传输下一个信息块,从而保证能够接收到全部数据。

3. Ymodem 协议的最低要求

  所有声称支持 Ymodem 协议的项目必须满足以下最低要求:

  • 发送端应在第一个数据包中发送路径名(文件名)。
  • 路径名应为以 “NULL” 结尾的 ASCII 字符串,如下所述:
  •  1)除非有特别要求,否则只发送文件名部分。
  •  2)不发送驱动器符号。
  •  3)不区分文件名中大小写字母的系统应仅以小写形式发送路径名。
  • 接收端应使用第一个数据包中发送的路径名作为接收文件名。
  • 当接收端接收到第一个数据包并成功打开输出文件后,应该返回一个 “ACK” 字符给发送端用来确认这个数据包,然后接收端再发送 “C” 或 “NAK” 来开始进行正常的 Ymodem 传输。
  • 接收端在接收每个文件时要能接受 128 字节和 1024 字节两种数据包的任意混合发送。发送端可以在 1024 字节和 128 字节两种数据包之间任意切换发送。
  • 发送端不能更改未确认的数据包的长度。
  • 在每次文件传输的末尾,发送端只能发送最多 10 次 “EOT” 字符,直到它收到一个 “ACK” 字符。(这是 Xmodem 规范的一部分。)
  • 发送路径名为空的路径名数据包来表示传输会话的结束,该路径名数据包应与其它路径名数据包一样被确认。

  没有满足以上要求的程序不兼容 Ymodem 协议,不应被描述为支持 Ymodem 协议。

4. Ymodem 协议帧详解

4.1 帧格式

  Ymodem 有两种帧格式,主要区别是数据长度的不同。

名称

结构

长度(byte)

标识符

备注

帧头

SOH/STX

1

0x01/0x02

表示帧格式类型;

SOH 为 128 字节帧,STX 为 1024 字节帧;

帧序号

FN

1

帧序号为 1 个字节,取值范围为 0~255;

当帧序号大于 255 后,序号重新从 0 开始累加;

帧序号反码

XFN

1

帧序号的反码,数值为 0xFF-FN;

数据

DATA

128/1024

帧头是 SOH 的数据帧,数据为 128 字节,该类型帧的总长度为 133 字节;

帧头是 STX 的数据帧,数据是 1024 字节,该类型帧总长度为 1029 字节;

校验

CRC

2

Ymodem 采用的是 CRC16 校验算法,校验值为 2 字节,传输时 CRC 高八位在前,低八位在后;

CRC 计算的是数据部分,不包含帧头、帧序号和帧序号反码;

4.2 帧命令

命令

命令码

备注

SOH

0x01

start of 128-byte data packet

STX

0x02

start of 1024-byte data packet

EOT

0x04

end of transmission

ACK

0x06

acknowledge

NAK

0x15

negative acknowledge

CA

0x18

two of these in succession aborts transfer

C

0x43

‘C’ == 0x43, request command

ABORT1

0x41

‘A’ == 0x41, abort by user

ABORT2

0x61

‘a’ == 0x61, abort by user

4.3 起始帧

  Ymodem 的起始帧并不直接传输文件的数据,而是将文件名和文件大小放在数据段中进行传输。
它的帧结构如下所示:

名称

结构

长度(byte)

标识符

备注

帧头

SOH/STX

1

0x01

起始帧为128字节帧;

帧序号

FN

1

0x00

起始帧的帧序号固定为 0x00;

帧序号反码

XFN

1

0xFF

起始帧的帧序号反码固定为 0xFF;

数据

FILENAME

要传输的文件名;

数据

FILESIZE

要传输的文件大小;

数据

NULL

若 FILENAME 和 FILESIZE 加起来不满 128 字节则以 0x00 填充剩余字节;

校验

CRC

2

数据部分的 CRC 校验;

  • 帧头为 SOH,表示起始帧中包含着128个字节的数据。
  • 起始帧帧序号固定为 0x00,帧序号反码为 0xFF。
  • FILENAME 是要传输的文件名,如 Template.bin,它在数据帧中的格式为:0x54,0x65,0x6D,0x70,0x6C,0x61,0x74,0x65,0x2E,0x62,0x69,0x6E,0x00,也就是把 ASCII 码转成十六进制,但是最后一定要在文件名后加上 0x00,表示文件名的结束。
  • FILESIZE 是要传输的文件大小,如上面的 Template.bin 大小 107544 byte,转换成十六进制就是 0x1A418。它在数据帧中的格式可以是十进制数的 0x31,0x30,0x37,0x35,0x34,0x34,也可以是十六进制数的 0x30,0x78,0x31,0x41,0x34,0x31,0x38,同样最后要加上 0x00 表示结束。
  • NULL 是数据部分若 FILENAME 和 FILESIZE 加起来不满 128 字节则以 0x00 填充剩余字节。
  • CRC 表示的是数据部分的 CRC 校验,不包含帧头、帧序号和帧序号反码。校验值为 2 字节,传输时 CRC 高八位在前,低八位在后。
4.4 数据帧

  YModem 数据帧会将数据段用来传输文件。
它的帧结构如下所示:

名称

结构

长度(byte)

标识符

备注

帧头

SOH/STX

1

0x01/0x02

数据帧可以是 128 字节帧或 1024 字节帧;

帧序号

FN

1

数据帧帧序号为 0~255;

帧序号反码

XFN

1

帧序号的反码,数值为0xFF-FN;

数据

DATA

要传输的数据;

数据

FILL

若 DATA 不满 128/1024 字节则以 0x1A 填充剩余字节;

校验

CRC

2

数据部分的 CRC 校验;

  • 帧头为 SOH 时,表示数据帧的数据段为 128 个字节;帧头为 STX 时,表示数据帧的数据段为 1024 个字节。
  • 数据帧帧序号的取值范围为 0~255,帧序号反码是它的取反;
  • DATA 表示要传输的文件数据;
  • FILL 是数据部分若 DATA 不满 128/1024 字节则以 0x1A 填充剩余字节。
  • CRC 表示的是数据部分的 CRC 校验,不包含帧头、帧序号和帧序号反码。校验值为 2 字节,传输时 CRC 高八位在前,低八位在后。
4.5 结束帧

  YModem 的结束帧也采用帧头为 SOH 的 128 字节帧,它的结构如下:

名称

结构

长度(byte)

标识符

备注

帧头

SOH

1

0x01

结束帧为 128 字节帧;

帧序号

FN

1

0x00

结束帧的帧序号固定为 0x00;

帧序号反码

XFN

1

0xFF

结束帧的帧序号反码固定为 0xFF;

数据

DATA

128

结束帧的数据部分不存放任何信息,全部用 0x00 填充;

校验

CRC

2

数据部分的 CRC 校验;

  • 帧头为 SOH,表示结束帧中包含着 128 个字节的数据。
  • 结束帧帧序号固定为 0x00,帧序号反码为 0xFF。
  • 结束帧的 128 字节的数据部分不存放任何信息,即全部用 0x00 填充。
  • CRC 表示的是数据部分的 CRC 校验,不包含帧头、帧序号和帧序号反码。校验值为 2 字节,传输时 CRC 高八位在前,低八位在后。

5. 文件传输过程

  文件的传输过程我们用具体的例子来说明。将大小为 107544 byte 的文件 “Template.bin” 作为传输对象,则它的传输过程如下:

ymodem securecrt ymodem securecrt eta_ymodem securecrt_05

  • 当发送端选择完发送文件后则进入准备发送文件状态。
  • 当接收端想要开始接收文件时发送命令 ‘C’ 请求发送端开始传输文件,然后开始等待发送端的起始帧。如果发送端没有发送起始帧,则接收端可选择超时退出或者继续发送命令 ‘C’ 请求发送端开始传输文件。
  • 发送端在开始时处于准备发送文件状态,等待接收端发送命令 ‘C’。在发送端收到命令 ‘C’ 后发送起始帧给接收端,内容如下(文件名为 Template.bin,文件大小为 107544 byte):
    SOH 00 FF FILENAME[54 65…6E 00] FILESIZE[31 30…34 00] NULL[108] CRC
    然后发送端开始等待接收端发送 ‘ACK’。
  • 当接收端收到起始帧,CRC 校验通过且确定要接收此文件后,则发送 ‘ACK’ 给发送端。
  • 发送端收到 ‘ACK’ 后则开始等待接收端的“请求开始传输数据”信号,即重新进入等待接收端发送命令 “C” 的状态。
  • 接收端发送命令 ‘C’,请求发送端开始传输数据。
  • 发送端在收到命令 ‘C’ 后,开始发送数据帧。内容如下:
    STX 01 FE DATA[1024] CRC
    然后发送端开始等待接收端发送 ‘ACK’。
  • 接收端收到数据帧后,返回一个 ‘ACK’,然后等待接收下一个数据帧,再继续返回 ‘ACK’。直到所有数据传输完毕。
  • 数据传输完毕后,发送端发送 ‘EOT’ 命令给接收端,接收端第一次收到 ‘EOT’ 命令后返回 ‘NAK’,要求进行二次确认。发送端收到 ‘NAK’ 后,重发 ‘EOT’ 命令。接收端第二次收到 ‘EOT’ 命令,返回 ‘ACK’ 应答,确认文件传输完毕。
  • 最后接收端发送命令 ‘C’ 请求发送端开启下一个文件传输,发送端在没有第二个文件要传输的情况下,发送结束帧给接收端。内容如下:
    SOH 00 FF NULL[128] CRC
    在接收端返回 ‘ACK’ 后,正式结束数据传输。

6. STM32 代码解析

6.1 ymodem_rx 类图

ymodem securecrt ymodem securecrt eta_Ymodem_06



--- End ---