当前位置:   article > 正文

Xmodem 协议介绍及应用(基于 ESP-IDF)

xmodem

Xmodem 协议介绍及应用(基于 ESP-IDF)

目录

1. 介绍

Xmodem 和 Ymodem 是串口通信中广泛用到的异步文件传输协议。这个协议包括了文件的识别、传送的起止时间、错误的判断与纠正等内容。Xmodem、Ymodem 和 Zmodem 协议是最常用的三种通信协议。详情可以参考ymodem.txt。本文只介绍 Xmodem 和 Ymodem 协议,Zmodem 协议后续添加。

1.1 使用场景

Xmodem 和 Ymodem 协议是串口文件传输协议,顾名思义可用于通过串口相连的 ESP 设备与 MCU 之间的文件传输。当 MCU 设备作为接收端时,ESP 设备通过 WIFI、BLE 或者其他方式获取 MCU 固件或者配置文件,通过串口文件传输协议传输到 MCU 端,MCU 根据接收到的固件或者配置文件进行升级或配置;当 MCU 设备作为发送端时,通过串口文件传输协议将 MCU 的日志或者配置文件等传输到 ESP 设备端,ESP 设备上传文件至云平台或者服务器。

例如: ESP 设备将从 OTA 平台获取到的固件通过 Xmodem 协议传输到 MCU 设备,从而实现 MCU 固件的 OTA 升级
在这里插入图片描述

1.2 协议介绍

1.2.1 Xmodem 协议

Xmodem 协议最早是以 128 字节块的形式传输数据,并且每个块都使用校验和进行错误检测。后面衍生出使用循环冗余校验方式 (CRC16) 和支持 1024 字节块的传输协议 (Xmodem-1k)。

1.2.2 Ymodem 协议

Ymodem 协议是 Xmodem 协议的改良版,以 1024 字节块的形式传输数据,并且支持传输多个文件。一般 Ymodem 协议是使用 CRC16 进行校验。

1.3 协议特点

Xmodem 和 Ymodem 协议传输由接收程序和发送程序完成。先由接收程序发送协商字符协商校验方式,协商通过之后,发送程序开始发送数据包。接收程序接收到一个完整的数据包之后,按照协商的校验方式对数据包进行校验,校验通过之后发送确认字符,校验失败则发送否认字符。发送程序收到确认字符后继续发送下一包,收到否认字符后重传数据包。

1.4 协议解析

Xmodem 和 Ymodem 从控制符定义和帧包格式上是基本一致的。

1.4.1 控制符定义

定义取值作用
SOH0x01modem 128 字节头标志
STX0x02modem 1024 字节头标志
EOT0x04发送结束标志
ACK0x06应答标志
NAK0x15非应答标志
CAN0x18取消发送标志
CRC160x43使用 CRC16 校验标志

1.4.2 帧包格式

Byte 1Byte 2Byte 3Byte 4- Byte 131Byte 132- Byte 133
头标志包序列~包序列包数据CRC16(2 Byte)

说明:

  • 该帧是 Xmodem 使用 CRC16 校验方式,如果使用 Xmodem-1k 或者 Ymodem,帧格式 Byte 4 - Byte 131 (128 字节) 需要增大为 Byte 4 - Byte 1027 (1024字节)。
  • Xmodem 如果使用校验和,帧格式 Byte 132 - Byte 133 只需要占用一个字节。
  • Byte 3 是 Byte 2 按位取反,Byte 2 取值范围 0 - 255,超过 255 后从 0 递增。

1.4.3 交互流程

流程里 NAK, ACK, CAN, CRC16 和 EOT 是没有包头和数据,只是一个单独的字符数据。

1.4.3.1 Xmodem 校验和交互流程
SenderFlowReceiver
<—NAK
Timeout after 3 seconds
<—NAK
| SOH | 0x01 | 0xFE | Data[0-127] | Checksum |—>Packet ok
<—ACK
| SOH | 0x02 | 0xFD | Data[0-127] | Checksum |—>Miss the packet
<—NAK
| SOH | 0x02 | 0xFD | Data[0-127] | Checksum |—>Packet ok
Miss the ACK<—ACK
| SOH | 0x02 | 0xFD | Data[0-127] | Checksum |—>Packet ignore
<—ACK
| SOH | 0x03 | 0xFC | Data[0-127] | Checksum |—>Checksum error
<—NAK
| SOH | 0x03 | 0xFC | Data[0-127] | Checksum |—>Packet ok
<—ACK
| EOT |—>Packet ok
Finished<—ACK
1.4.3.2 Xmodem CRC16 交互流程

计算 CRC16 校验的除数多项式为X ^ 16 + X ^ 12 + X ^ 5 + 1,信息报中的 128 数据字节将参加 CRC16 校验的计算,在发送端 CRC16 的高字节在前,低字节在后。

SenderFlowReceiver
<—‘C’
Timeout after 3 seconds
<—‘C’
| SOH | 0x01 | 0xFE | Data[0-127] | CRCH | CRCL |—>Packet ok
<—ACK
| SOH | 0x02 | 0xFD | Data[0-127] | CRCH | CRCL |—>Miss the packet
<—NAK
| SOH | 0x02 | 0xFD | Data[0-127] | CRCH | CRCL |—>Packet ok
Miss the ACK<—ACK
| SOH | 0x02 | 0xFD | Data[0-127] | CRCH | CRCL |—>Packet ignore
<—ACK
| SOH | 0x03 | 0xFC | Data[0-127] | CRCH | CRCL |—>Checksum error
<—NAK
| SOH | 0x03 | 0xFC | Data[0-127] | CRCH | CRCL |—>Packet ok
<—ACK
| EOT |—>Packet ok
Finished<—ACK

说明:

  • 相比于 Xmodem 校验和, Xmodem CRC16 是发送控制字符 C,而校验和发送控制字符 NAK,并且 CRC16 校验字段占 2 Byte。
  • 如果使用 Xmodem-1k 协议发送 1024 字节的数据,只需要将数据头标志由 SOH 替换为 STX,数据部分占 1024 字节。
  • 如果发送的数据不满 128 字节或者 1024 字节,使用 0x1A 填充。
1.4.3.3 Ymodem 交互流程

Ymodem 协议的起始帧并不直接传输文件的数据,而是将文件名与文件的大小放在数据帧中传输。它的数据帧结构如下:

Byte 1Byte 2Byte 3Byte 4- Byte 131Byte 132- Byte 133
SOH0x000xFFFilename | Filesize | NULCRC16(2 Byte)

说明:

  • 头标志是 SOH,包序列固定是 0x00。
  • Filename 是传输的文件名字,比如 hello_world.bin,它在起始帧中的格式为: 68 65 6c 6c 6f 5f 77 6f 72 6c 64 2e 62 69 6e 00,也就是把 ASCII 码转成十六进制,最后的 0x00 代表文件名结束。
  • Filesize 是要传输的文件的大小,比如文件大小为 120 KB,转换为 120 * 1024 = 122880 Byte,转化为十六进制为 0x1E00,它在起始帧中的格式为: 31 45 30 30 00,对应 ASCII 1E00,最后的 0x00 代表文件长度结束。
  • 最后 NUL 代表剩余不足 128 Byte 部分用 0x00 填充。

Ymodem 协议的结束帧与起始帧类似,结构如下:

Byte 1Byte 2Byte 3Byte 4- Byte 131Byte 132- Byte 133
SOH0x000xFFNULCRC16(2 Byte)

文件传输流程:

SenderFlowReceiver
<—‘C’
Timeout after 3 seconds
<—‘C’
| SOH | 0x00 | 0xFF | Filename | Filesize | NUL | CRCH | CRCL |—>Packet ok
<—ACK
| STX | 0x01 | 0xFE | Data[0-1024] | CRCH | CRCL |—>Packet ok
<—ACK
| STX | 0x02 | 0xFD | Data[0-1024] | CRCH | CRCL |—>Packet ok
Miss the ACK<—ACK
| STX | 0x02 | 0xFD | Data[0-1024] | CRCH | CRCL |—>Packet ignore
<—ACK
| STX | 0x03 | 0xFC | Data[0-1024] | CRCH | CRCL |—>Packet ok
<—ACK
| SOH | 0x04 | 0xFB | Data[0-127] | CRCH | CRCL |—>Packet ok
<—ACK
| EOT |—>Packet ok
<—NAK
| EOT |—>Packet ok
<—ACK
<—‘C’
| SOH | 0x00 | 0xFF | NUL | CRCH | CRCL |—>Packet ok
Finished<—ACK

1.5 方案对比

1.5.1 对比 AT 透传升级 MCU

方案AT 透传Xmodem
数据校验和不支持支持
文件的识别不支持支持
错误的判断不支持支持
序列化传输不支持支持

相比于 AT 透传实现 MCU 升级,Xmodem 协议具有每笔数据报文的完整性校验、数据报文的有序传输、数据报文的乱序丢包判断和传输文件的识别等等优势。

1.5.2 对比其他串口文件传输协议升级 MCU

相关其他串口文件传输协议,请参考维基百科

归纳总结:

  • 当前常用的串口文件传输协议就只有 Xmodem、Ymodem 和 Zmodem,并且它们的 licensePublic domain
  • 它们支持数据错误检查机制: 校验和和出错重传。

使用 Xmodem 和 Ymodem 串口文件传输协议实现 MCU 升级,对于 MCU 侧可按照标准协议文档实现,对于 ESP 设备侧可参考文档后续章节介绍。

2. 目的

本文基于 Xmodem 和 Ymodem 协议规范,针对 ESP8266_RTOS_SDK 和 ESP-IDF 平台开发了基于 UART 传输的文件传输协议组件。支持以下 Xmodem 和 Ymodem 组合协议功能。

XmodemYmodem
校验和支持支持
CRC16支持支持
1K + CRC16支持支持

本文将介绍如何使用该组件提供的接口进行串口文件传输。

3. 硬件准备

  • linux 环境
    用来编译 & 烧写 & 运行等操作的必需环境。

windows 用户可安装虚拟机,在虚拟机中安装 linux。

  • ESP 设备
    ESP 设备包括 ESP芯片ESP模组ESP开发板等。

  • USB串口 杜邦线
    连接 PC 和 ESP 设备,用来烧写/下载程序,通过串口 UART 传输文件协议,查看 log 等。

4. 环境搭建

如果您熟悉 ESP 开发环境,可以很顺利理解下面步骤;如果您不熟悉某个部分,比如编译,烧录,需要您结合官方的相关文档来理解。如您需阅读 ESP-IDF 编程指南文档等。

4.1 编译器环境搭建

  • ESP8266 平台:根据官方链接Get toolchain,获取 toolchain。
  • ESP32 平台:根据官方链接工具链的设置,下载 toolchain。

toolchain 设置参考 ESP-IDF 编程指南

4.2 烧录工具/下载工具获取

  • ESP8266 平台:烧录工具位于 ESP8266_RTOS_SDK./components/esptool_py/esptool/esptool.py
  • ESP32 平台:烧录工具位于 esp-idf./components/esptool_py/esptool/esptool.py

esptool 功能参考:

$ ./components/esptool_py/esptool/esptool.py --help
  • 1

5. SDK 准备

  • esp-xmodem,通过该 SDK 可实现 Xmodem 和 Ymodem 协议应用。
  • Espressif SDK
    • ESP32 平台: ESP-IDF,支持 v4.0 之后版本。
    • ESP8266 平台: ESP8266_RTOS_SDK,支持 v3.3 之后版本。

6. 功能介绍

功能框架如下:

Xmodem Sender 和 Xmodem Receiver 上层遵循 Xmodem 协议,数据传输通过 transport 层将协议数据写入 UART 串口,然后 Xmodem 主机和从机通过串口通信协议传输数据。
在这里插入图片描述

6.1 文件的传输与接收

6.1.1 配置 UART 传输层

esp_xmodem_transport_config_t transport_config = {
    .baud_rate = 921600,
    #ifdef CONFIG_IDF_TARGET_ESP32
    .uart_num = UART_NUM_1,
    .swap_pin = true,
    .tx_pin = 17,
    .rx_pin = 16,
    .cts_pin = 15,
    .rts_pin = 14,
    #endif
};
esp_xmodem_transport_handle_t transport_handle = esp_xmodem_transport_init(&transport_config);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • ESP8266 默认只能使用 UART0 进行传输和接收,由于 UART0 会存在 bootloader 相关打印,为了减少此类打印数据,可以使能 swap_pin 功能,将传输接收口 swap 到 IO15 和 IO13 上,bootloader 的输出还是通过 UART0 口输出。
  • ESP32 则可以使用 UART0,UART1 和 UART2,建议使用 UART1 进行文件传输和接收,UART0 用作 LOG 输出。
  • baud_rate 值越大,传输速率就越快。
  • recv_timeout 是串口读取 ring buffer 的超时时间,默认建议选择 100 ms。

6.1.2 配置 Xmodem role

esp_xmodem_config_t config = {
    .role = ESP_XMODEM_SENDER,
    .event_handler = xmodem_sender_event_handler,
    .support_xmodem_1k = true,
};
esp_xmodem_handle_t sender = esp_xmodem_init(&config, transport_handle);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • role 代表是 sender 还是 receiver, 后续调用 esp_xmodem_start 会根据 role 去选择起 sender 还是 receiver 去处理。
  • support_xmodem_1k 仅对于发送者 (sender) 有效,表示是否支持按照 Xmodem-1k 方式传输数据。如果不设置,默认 support_xmodem_1kfalse,数据按照 128 字节发送。 如果设置 support_xmodem_1ktrue,就会按照 1024 字节发送。如果数据少于 1024 字节,大于 128 字节,就会按照 1024 字节发送,不足 1024 字节部分填充 0x1A 后发送。如果数据少于 128 字节,就会按照 128 字节发送,不足 128 字节部分填充 0x1A 后发送。
  • event_handler 用于注册事件 event,根据相应的 event 处理不同事件,相应逻辑处理可以参考示例。
 esp_xmodem_config_t config = {
    .role = ESP_XMODEM_RECEIVER,
    .crc_type = ESP_XMODEM_CRC16,
    .event_handler = xmodem_receiver_event_handler,
    .recv_cb = xmodem_data_recv,
    .cycle_max_retry = 25,
};
esp_xmodem_handle_t receiver = esp_xmodem_init(&config, transport_handle);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • crc_type 是 receiver 支持的校验方式。
  • recv_cb 仅对于接收者 (receiver) 有效,用于底层接收到文件给用户层的回调函数。相应逻辑处理可以参考 (recevier) 示例。

6.1.3 启动 Xmodem

esp_xmodem_start(sender);
  • 1
  • 根据返回值 ESP_OK 判断有没有启动成功.
  • 连接到 Xmodem receiver 后,会上报 ESP_XMODEM_EVENT_CONNECTED 事件,然后处理相应逻辑。本例中是起了一个http client task 来下载文件。
esp_xmodem_start(receiver);
  • 1
  • 调用该函数后,receiver 会根据crc_type 的值发 ‘C’ 或者 NAK,一旦有 sender 发送数据,就会上报 ESP_XMODEM_EVENT_CONNECTED 事件,并且数据会上报至注册的 recv_cb 中。如果是文件传输,会在 ESP_XMODEM_EVENT_ON_FILE 事件中上报文件名和文件长度。

7. 编译&烧写&运行

7.1 编译

7.1.1 导出编译器

参考 工具链的设置
设置 IDF_PATH,运行 $IDF_PATH/install.sh 安装相关工具,执行 $IDF_PATH/export.sh 导出路径。

7.1.2 示例编译

  • make 执行如下命令,可以通过 make menuconfig 修改串口烧录配置
cd esp-xmodem/examples/xmodem_receiver
make defconfig
make
  • 1
  • 2
  • 3
  • cmake 执行如下命令,可以通过 idf.py menuconfig 修改串口烧录配置
cd esp-xmodem/examples/xmodem_receiver
idf.py build
  • 1
  • 2

7.2 烧写

7.2.1 Linux 平台烧写

  • 对于 make 执行 make flash,对于 cmake 执行 idf.py flash
  • 使用 make erase_flash 或者 idf.py erase_flash 擦除 flash。
  • 使用 make monitor 或者 idf.py -p (PORT) monitor 查看串口输出。

7.2.1 Windows 平台烧写

使用 Flash 下载工具(ESP8266 & ESP32) 烧录 Xmodem 示例固件。

  • 打开 flash download tool, ESP8266 的烧录配置如下:
    在这里插入图片描述

  • 打开 flash download tool, ESP32 的烧录配置如下:
    在这里插入图片描述

点击 start 进行烧录, 烧录成功后按 EN 键重启开发板。

7.3 运行

示例可以通过 Linux 系统命令 rzsz 配合测试。这两者支持 Xmodem,Ymodem 和 Zmodem 文件传输协议。如果用户发现 Linux 系统上找不到该命令,可以执行如下命令安装。

sudo apt-get install lrzsz
  • 1

rz 用于接收 sender 发送来的文件,sz 用于发送文件至 receiver。详细命令可以参考 rz --help 或者 sz --help

7.3.1 示例 xmodem_receiver (用于在主机上通过 xmodem 协议给模组从机进行 OTA)

该示例用于充当 receiver 来接收 sender 发送的文件,利用文件进行 OTA。详细操作请参考示例下对应的 README 文件。
对于 sender 可以使用如下命令进行发送 OTA 文件:

sz --ymodem (file name or pure data) >/dev/ttyUSB0 </dev/ttyUSB0
  • 1

其中 ttyUSB0 是用于与 receiver 进行文件传输的串口。
设备侧log:

...
[17:46:56.538][0;32mI (286) uart: queue free spaces: 10[0m
[17:46:56.575][0;32mI (3286) xmodem_receive: Waiting for Xmodem sender to send data...[0m
[17:46:59.580][0;32mI (6286) xmodem_receive: Waiting for Xmodem sender to send data...[0m
[17:47:02.618][0;32mI (6292) xmodem_receive: ESP_XMODEM_EVENT_CONNECTED[0m
[17:47:02.618][0;32mI (6294) xmodem_receive: This is a file begin transfer[0m
[17:47:02.618][0;32mI (6298) xmodem_receive: ESP_XMODEM_EVENT_ON_FILE[0m
[17:47:02.618][0;32mI (6306) xmodem_receive: file_name is xmodem_receiver.bin, file_length is 176704[0m
[17:47:02.618][0;32mI (6339) xmodem_receive: Starting OTA...[0m
[17:47:02.641][0;32mI (6340) xmodem_receive: Writing to partition subtype 17 at offset 0x110000[0m
[17:47:02.641][0;32mI (9305) xmodem_receive: esp_ota_begin succeeded[0m
[17:47:05.607][0;32mI (9306) xmodem_receive: Please Wait. This may take time[0m
[17:47:05.607][0;32mI (18056) xmodem_receive: Receive EOT data[0m
[17:47:14.388][0;32mI (18059) xmodem_receive: Receive EOT data again[0m
[17:47:14.388][0;32mI (18066) xmodem_receive: This is a file end transfer[0m
[17:47:14.388][0;32mI (18067) xmodem_receive: ESP_XMODEM_EVENT_FINISHED[0m
...
[17:47:14.531][0;32mI (18224) xmodem_receive: esp_ota_set_boot_partition succeeded[0m
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

7.3.2 示例 xmodem_sender (用于在主机上通过 xmodem 协议接收模组从机进行文件传输)

该示例用于充当 sender 来发送通过 http 下载的文件。Linux 电脑上可以通过命令 python -m SimpleHTTPServer 起一个 Http Server。详细操作请参考示例下对应的 README 文件。
对于 receiver 可以使用如下命令进行接收文件:

rz --ymodem >/dev/ttyUSB0 </dev/ttyUSB0
  • 1

其中 ttyUSB0 是用于与 receiver 进行文件传输的串口。
设备侧 log:

...
[17:40:45.177][0;32mI (481) example_connect: Connecting to HUAWEI_888...[0m
[17:40:45.188][0;32mI (1768) wifi:state: 0 -> 2 (b0)
[17:40:46.472][0m[0;32mI (1782) wifi:state: 2 -> 3 (0)
[17:40:46.485][0m[0;32mI (1790) wifi:state: 3 -> 5 (10)
[17:40:46.493][0m[0;32mI (1829) wifi:connected with HUAWEI_888, aid = 1, channel 1, HT20, bssid = 34:29:12:43:c5:40
[17:40:46.549][0m[0;31mE (1839) wifi: AES PN: 0000000000000000 <= 0000000000000000[0m
[17:40:46.549][0;32mI (4270) tcpip_adapter: sta ip: 172.168.30.131, mask: 255.255.255.0, gw: 172.168.30.1[0m
[17:40:49.019][0;32mI (4275) example_connect: Connected to HUAWEI_888[0m
[17:40:49.019][0;32mI (4279) example_connect: IPv4 address: 172.168.30.131[0m
[17:40:49.019][0;32mI (4288) xmodem_send: Connected to AP, begin http client task[0m
[17:40:49.019][0;32mI (4298) uart: queue free spaces: 10[0m
[17:40:49.019][0;32mI (14300) xmodem_send: Connecting to Xmodem receiver(1/25)[0m
[17:40:59.011][0;32mI (23638) xmodem_send: ESP_XMODEM_EVENT_CONNECTED[0m
[17:41:08.349][0;32mI (24771) xmodem_send: Send image success[0m
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/183883
推荐阅读
相关标签
  

闽ICP备14008679号