嵌入式设备在无法使用网络和USB的情况下如何进行文件传输

问题背景

ST 测试时出现一个问题,路由器(采用Openwrt系统)的console无法正常显示shell提示符,正常情况下是

root@DeviceName:/#

这样的,出问题时是下面这样的,用户名不见了,设备名变成了none.

@(none):/#

不仅如此,执行ls发现根目录很多文件都不存在了。最初我和组长认为可能是存储固件的nand flash出了问题,所以想把固件dump出来换到另一块板子上,所以先使用nanddump指令把固件保存到fw.img文件中:

nanddump /dev/mtd8 -f /tmp/fw.img

接着想要通过tftp传到外面,但是失败了,ifconfig查看网络信息发现没有任何IP,ps查看进程信息发现绝大部分进程都没有启动,很显然,缺失的文件过多,板子无法正常使用网络传输了。那么USB呢,对了我用的这款路由器带有USB功能,插上以后没有任何反应,不过也是意料之中,相关的USB检测进程木有起来呗。

那么现在问题来了,在无法使用网络和USB的情况下,如何把数据从板子copy到PC呢?下面介绍两种方法。

解决方法

uboot tftp文件传输

我最初想到的方法就是uboot,通过uboot把数据dump到内存,然后使用uboot中的tftp把数据传出来,相关指令如下:

nand read <ram_addr> <flash_addr> <size>
tftpput <ram_addr> <size> <file_name>

# example
nand read 0x84000000 0x1480000 0x1860000
tftpput 0x84000000 0x1860000 Fireware.img

这里涉及到两个指令nand readtftpputnand flash的block size是128K,所以flash地址以及size都设置为128K的整数倍

  • ram_addr - 内存地址,也是平常fw_recovery存放固件的地址
  • flash_addr - 存放固件的flash地址,需要查看代码相关配置文件查询
  • size - 读取数据的长度,大概设置为大于固件大小的值

在uboot启动时会将自身IP设为192.168.1.1,所以只需把PC端的IP设为静态IP 192.168.1.10即可传输。然而还有一个问题,出现问题的设备uboot并不包含tftpput指令,这是uboot版本问题,这就尴尬了。。。显然此路不通。

串口传输

重点来了,在我黔驴技穷的情况下,我组长很平静的说出了串口传输的方法,绝对的骚操作!!!

乍一听,串口传输可能会觉得很一般,不就是通过串口把数据传出来么,当年单片机开发用的可溜了好吧。咱不急,慢慢看

这个方法在linux系统很方便,windows系统没研究过。我使用的是ubuntu 18.04, 进入正题,使用tmux打开两个窗口,如果没有tmux或者screen则打开两个终端窗口也是一样的。

  • 发送窗口

在super模式下,将文件fw.img通过串口打印出来

litreily@litreily-Aspire-4750:~ >> sudo su
root# cat > /dev/ttyUSB0
cat fw.img

这个窗口通过cat指令向串口发送指令cat fw.img,那么板子中的文件fw.img数据就会开始传输。

  • 接收窗口
sudo cat /dev/ttyUSB0 > ~/fw.img

serial transfer

接收窗口通过cat串口接收输入数据并重定向至本地文件~/fw.img。注意,执行接收窗口的指令,再执行发送窗口的指令,这样就保证了接收数据的完整性。

是不是很骚气,这也充分展示了linux系统下一切皆是文件的厉害之处,通过简单的cat指令就可以玩转串口数据。

扩展补充:minicom

针对串口传输,推荐个linux上极为好用的串口终端minicom,类似于windows系统中的tera term

sudo apt install minicom

安装后,在串口连接状态下,通过以下指令找到串口设备/dev/ttyUSB0

$ ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 9月  12 22:42 /dev/ttyUSB0

然后启动minicom,首次启动需要配置些参数

sudo minicom -s

+-----[configuration]------+
| Filenames and paths      |
| File transfer protocols  |
| Serial port setup        |
| Modem and dialing        |
| Screen and keyboard      |
| Save setup as dfl        |
| Save setup as..          |
| Exit                     |
| Exit from Minicom        |
+--------------------------+

选择Serial port setup,然后根据下面的提示设置Serial Device为上面查找到的/dev/ttyUSB0,将Hardware Flow Control设置为no

+-----------------------------------------------------------------------+
| A -    Serial Device      : /dev/ttyUSB0                              |
| B - Lockfile Location     : /var/lock                                 |
| C -   Callin Program      :                                           |
| D -  Callout Program      :                                           |
| E -    Bps/Par/Bits       : 115200 8N1                                |
| F - Hardware Flow Control : No                                        |
| G - Software Flow Control : No                                        |
|                                                                       |
|    Change which setting?                                              |
+-----------------------------------------------------------------------+

选好后回车,在返回菜单中选择Save setup as dfl,下次直接通过sudo minicom就可以使用了。 退出minicom使用快捷键Ctrl A Z然后按x即可。

后续

最终发现不是固件的问题,而是测试人员操作失误,将rm /opt/* 写成了rm /opt/ *,没错就是多了个空格,把根目录能删的都删了,至于怎么发现的,根据测试提供的console log。。。

虽然这个传输后的fw.img没有派上用场,但学到了一个可以特定情况下很有用的冷知识也是很不错的,关键时候挺管用的。不过这个方法也有其局限性,就是如果在cat过程中,板子自动打印了许多其它类型的log,就会把数据搞乱。