交叉编译lrzsz串口传输工具及踩坑过程
嵌入式Linux开发的过程中传输文件是个挺麻烦的事,主要有三种方式:
- SD卡拷贝(需要反复插拔,mount/umount比较麻烦)
- TFTP网络传输(速度快,但需要网线)
- 串口传输(无需额外接口,但速度很慢)
本文主要介绍君正T40平台上使用串口传输文件的方式。
正篇:lrzsz工具编译使用教程
编译工具链准备
下载所用开发板配套的工具链,如君正T40平台提供的mips-linux-gnu-xxx
,并配置好环境变量
下载准备
lrzsz源码
地址:https://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz
在PC上解压
支持串口传输的shell客户端,如SecureCRT(正版需要收费,就不贴链接了,自行百度)
交叉编译
配置编译参数
方便起见,可以在源码根目录新建一个
run.sh
文件,填入以下内容HOST``BUILD
改成你的开发板的架构1
2
3
4
5
6
7
8
9
10
11
12
CUR_DIR=`pwd`
HOST=mips-linux-gnu
BUILD=mips-linux-gnu
INSTALL_PREFIX=${CUR_DIR}/lrzsz_out
mkdir -p ${INSTALL_PREFIX}
LDFLAGS=-muclibc
echo "ac_cv_prog_CC=${ac_cv_prog_CC='mips-linux-gnu-gcc'}" >> mips-linux-gnu.cache
./configure --prefix=${INSTALL_PREFIX} --host=${HOST} --build=${BUILD} --cache-file=./mips-linux-gnu.cache执行
sh ./run.sh
生成MakeFile
文件执行
make && make install
编译在
./lrzsz_out/bin
目录下生成了lrz``lrx
等6个二进制文件,拷贝至开发板即可运行。lrz``lrx``lrb
分别表示Zmodem, Xmodem, Binary的模式从PC接收文件lsz``lsx``lsb
则表示相应模式的向PC发送文件一般用
lrz
和lsz
就行
开发板运行
- 将
lrz``lsz
二进制文件拷贝到/usr/bin或其他目录 - 为方便使用,重命名为
rz
和sz
接收文件
输入rz,回车,将自动弹出SecureCRT的传输文件窗口,选择文件->Add->OK即可发送
会有进度条,速度大概13KB/s左右吧,聊胜于无,大文件就算了//////
发送文件
过程也类似,输入:
1 | sz filename.jpg |
进度条自己开始走,如果用的是Win10,文件会出现在系统的 下载 目录下
正篇结束,看着很简单吧,然而这只是最理想的情况下,我在交叉编译那步开始踩坑,以下请听我细数:
踩坑之路
sh: lrz: not found!
当我将交叉编译后的二进制拷贝到板子上时,却无法运行!提示信息也有很强的误导性,我一度以为是路径问题。然而,我明明在这,你却not found
百度之后才了解到,not found一般有三种原因:
真的not found:目录下没有这个命令
有,但你不配:执行权限不够 -> chmod 777 即可解决
我人在,但心不在:程序运行需要的静态库或者动态库缺失
我遇到的显然不是第一二种,那看来就是依赖库缺失了。
排查依赖库
回到PC上,使用交叉编译工具链中的mips-linux-gnu-readelf
分析动态库
果然,需要libnsl.so.1
libc.so.6
这两个动态链接库,再回到开发板上确认下:
果然,/lib
和/system/lib
下都没找到他们的身影。
但没事,从交叉编译工具链那边复制过来不就行了?
1 | find -name "libc.so.6" |
find一下,也顺利找到了,胜利在望啊!
赶紧再逝一下!
依旧 not found!怎么可能!?不会是这2个库还有套娃依赖吧?
1 | mips-linux-gnu-readelf -d lrzsz_out/bin/libc.so.6 |
嗯,那继续,把ld-linux-mipsn8.so.1
加上总可以了吧。(既然这么说了那肯定没成功
那这个ld-linux-mipsn8.so.1
是何方神圣呢?
原来这是linux动态链接共享库的装载器,也就是一切动态库的根基,他存放的位置就没有那么随便了,必须固定在/lib
目录下,可以用mips-linux-gnu-readelf -a
命令查证:
可以看到,在程序头部指明了解释器的绝对路径
但不凑巧的是,我的开发板的/lib
目录是只读文件系统,无法新增文件
换个链接器
Linux的链接装载器不止这一种,那不如换个思路,看看这个板子支持哪个链接器。
欸,ld-uClibc-mipsn8.so.0
这个文件名长得很像啊!那能不能加个编译参数,指定用这个链接器呢?
在君正官方程序的MakeFile中找到了线索:
-muclibc
这个参数,就是帮助编译器选择使用gclib还是uclib动态库的,对于这个开发板,需要使用的正是uclib版本。
到这里,我以为胜利在望了,结果编译报错了,看来uclib的库并不全,叒有依赖缺失。
1 | make LDFLAG=-muclibc |
一路坎坷好不容易到这一步,唯一的希望似乎也被堵死了,但其实离成功不远了。换个思路,既然动态库不行,那能不能把他们打包成一个静态库?
静态库打包
1 | make install LDFLAGS=-static |
OHHHHHHHHH,终于成功了,可以看到程序已经没有动态链接部分了。上板运行也非常成功,只是二进制文件大一点(从190KB变为900KB,咱不差这点空间!)
总结
这原本只是一件小事,没想到牵扯出这么多问题,在解决问题的过程中我也被迫去学习了动态链接库,configure文件功能,MakeFile的参数含义,交叉编译工具使用等等。
Ref:
[1] lrzsz的交叉编译与使用
[2] lrzsz小工具的使用
交叉编译lrzsz串口传输工具及踩坑过程