使用 ascii-xfr 传输 rz 程序

最近继续折腾一些嵌入式设备,需要通过 UART 传输一些文件。一般来说直接使用 rz/sz 即可,但不幸的是 rz applet 并没有编译进这个设备的 busybox。同时由于一些蛋疼的原因,我们也不能重新烧写设备的 rootfs 镜像或者是从网络安装,那么就只能自己想办法解决咯……

基本思路是自己静态编译一份 rz 程序,然后从串口发送给嵌入式设备,然后再利用这个 rz 接收 sz。然后就能双向发送文件了。

设备上至少需要有cat命令和base64 -d。如果没有base64可以试试openssl base64 -d。如果还是没有那这篇文章的方法就不适用于你了。另外在设备上最好还要有一个 gzip 之类的压缩程序,可以显著缩短初次传输时间,以及一个 checksum 程序用于检查。我这里用了xzmd5sum

在主机上你需要有ascii-xfr程序。

编译 rz

你需要有一个能用的工具链,我的设备是 AArch64,直接使用了源里的 gcc。

1
2
3
4
5
6
7
8
# 下载代码
wget 'https://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz'
# 解压
tar xaf lrzsz-0.12.20.tar.gz
cd lrzsz-0.12.20
# 静态编译
CFLAGS='-Oz -static' CC=aarch64-linux-gnu-gcc ./configure --target=arm64-linux
make

如果你有对应设备的工具链也可以动态编译,这样编译出来的文件会更小。

使用 ascii-xfr 发送 rz

我这里使用picocom连接设备,其他程序比如minicomscreen请自行查阅手册寻找使用方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 接上文
cp src/lrz rz
# 进一步裁剪文件体积
aarch64-linux-gnu-strip --strip-all rz
# 计算 checksum 备用
md5sum rz
ee96d7186db0f5240040c183636a8c9d
# 压缩
xz -9 rz
# 编码成 BASE64
base64 rz.xz > rz.xz.64
# 连接设备,记得使用你自己设备的波特率
picocom -b 1500000 -s 'ascii-xfr -sn -c 1' /dev/ttyUSB0
# 在设备中准备接收
wimpy_board$ cat > rz.xz.64
# 按 Ctrl-A Ctrl-S,然后输入要发送的文件的文件名
*** file: rz.xz.64
# 等待字符滚完,然后按 回车 + Ctrl-D 退出 cat
# 传输速度是 1000Bps,我最终需要传输 420 多 KB,需要 7 分钟。
# 传输完毕后在设备上还原可执行文件
wimpy_board$ base64 -d rz.xz.64 > rz.xz
wimpy_board$ xz -d rz.xz
wimpy_board$ chmod +x rz
# 最后比较一下 md5 值,并确认可以正常运行
wimpy_board$ md5sum rz
ee96d7186db0f5240040c183636a8c9d
wimpy_board$ ./rz
# 连按 5 次 Ctrl-X 退出

使用 rz 接收 sz

有经验的朋友到这里可以直接右上角退出了,不过我还是记录一下做个备忘。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 按 Ctrl-A Ctrl-X 退出 picocom,然后再重新连接。
# 不带 -s 参数时 picocom 默认使用本机的 sz 发送文件。
picocom -b 1500000 /dev/ttyUSB0
wimpy_board$ ./rz
waiting to receive.**
# 按 Ctrl-A Ctrl-S,然后输入要发送的文件的文件名
*** file: src/lsz
$ sz -vv src/lsz
Sending: lsz
Bytes Sent:1173536 BPS:144649

Transfer complete

*** exit status: 0 ***