# 使用 Minicom 經由 Zmodem 在 Host 和開發板傳送檔案
我的 Minicom 版本:
```shell!
$ minicom --version
minicom version 2.7.1 (compiled Dec 23 2019)
Copyright (C) Miquel van Smoorenburg.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version
2 of the License, or (at your option) any later version.
```
Host 的 Ubuntu 版本:
```shell!
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```
以下示範用的開發板:
[Marvell ESPRESSObin v7](https://espressobin.net/tech-spec/)
## 安裝 & 設定 Minicom
1. 用以下指令安裝 Minicom:
```shell
$ sudo apt install minicom
```
2. 用以下指令開啟 Minicom:
```shell
$ sudo minicom -s
```
- 會看到以下這個設定 Minicom Configuration 的選單:
![image](https://hackmd.io/_uploads/BkEGjp0vR.png)
3. 在 `Serial port setup` 的選項按 `enter` 後會看到以下畫面:
![image](https://hackmd.io/_uploads/HJiIsp0vC.png)
- 想修改哪個選項,就按該選項最前面的英文字母,就可以修改該選項,譬如說想修改 `Serial Device`,那就按 `a` 就可以了。
:::info
這裡該怎麼設定,以我用過的 Marvell ESPRESSObin v7 這個開發板來講,[官方文件](https://wiki.espressobin.net/tiki-index.php?page=Serial+connection+-+Linux#Connecting_with_Minicom) 就有做很詳細的說明~這個開發板要設定的有 `A - Serial Device`、`E - Bps/Par/Bits`、以及 `F - Hardware Flow Control`。
- Marvell ESPRESSObin v7 是用 USB emulated serial port,是用 micro USB cable 跟 Host 連接,所以接上去後應該就會是 `/dev/ttyUSB0`。
- 但如果是直接跟 Host 的 Serial Port 連接,應該會是 `/dev/ttyS0`。
- 開發板的 Serial Port 的 Baud Rate 是多少,應該官方文件也都會有,以這個開發板來講是 115200。
- `Hardware Flow Control` 原本預設是 `Yes`,把它改成 `No`。
:::
4. 按 `esc` 回到上一層,也就是主選單的畫面,接下來要設定 `Filenames and paths`
這裡要設定 `Download directory` 和 `Upload directory`:
- `Download directory`:從開發板傳送到 Host 的檔案,你想存放在 Host 的哪個 directory
- `Upload directory`:若要從 Host 傳檔案到開發板,你想傳送的檔案是放在 Host 的哪個 directory
:::danger
這裡的兩個 Directory 都是指 Host 的 Directory 喔!
一個是從開發板傳送到 Host 的檔案要放在 Host 的哪個 Directory;一個是要從 Host 的哪個 Directory 傳送檔案到開發板。
我一開始以為 `Upload directory` 是指開發板的哪個 directory 要拿來存放從 Host 傳來的檔案,結果後續就一直失敗,卡關卡好久 QQ 😭😭😭😭😭
:::
![image](https://hackmd.io/_uploads/SymEsTRw0.png)
5. 設定完之後就回到上一層主選單,選 `Save setup as dfl` 將目前的 Configuration 設定成 Default,然後選 `Exit` 離開 Minicom configuration。
## Host 安裝 `lrzsz`
Host 和開發板都需要安裝 `lrzsz`,這樣才能用 Zmodem Protocol 來傳送檔案。
桌機如果是 Ubuntu 就用以下指令安裝:
```shell
$ sudo apt install lrzsz
```
我用這個指令安裝 `lrzsz`,後續若需要用 zmodem 傳東西則是用 `rz` 和 `sz`。
![image](https://hackmd.io/_uploads/ryW1paAwR.png)
## 開發板安裝 `lrzsz`
如果開發板連不上網路,那就需要在 Host 做 Cross-Compile,然後再把 `lrzsz` 的檔案放到開發板裡面。
1. 下載 `lrzsz` source code
- 這是 `lrzsz` 的作者 Uwe Ohse 的 `lrzsz` 的 GitHub 頁面:https://github.com/UweOhse/lrzsz
- 作者說若要下載 source code 的話,就下載這個連結的:http://ohse.de/uwe/testing/lrzsz-0.12.21rc.tar.gz
2. 用以下指令解壓縮:
```shell
$ tar -xzvf lrzsz-0.12.21rc.tar.gz
```
3. 解壓縮完之後會出現 `lrzsz-0.12.21rc` 這個資料夾,`cd` 進去。
4. 從 `INSTALL` 這份文件可以知道我們要先設定 configure:
- 我用的 Cross Compiler 是 `aarch64-linux-gnu-gcc`,所以設定 configure 時會需要指定 `CC=aarch64-linux-gnu-gcc`
- 作者建議要用 `CFLAGS="-O2"` 這個 Option
- 我們可以自己指定編譯完成後的執行檔要放在哪個資料夾,用 `--prefix=PATH` 這個 Option,像我就是用 `--prefix=/home/cpt1020/lrzsz/`
5. 執行以下指令設定 configure:
```shell
$ CC=aarch64-linux-gnu-gcc CFLAGS="-O2" ./configure --prefix=/home/cpt1020/lrzsz/
```
6. 執行以下指令開始編譯:
```shell
$ make install
```
7. 編譯完成後,會在剛剛 `--prefix=PATH` 所指定的 directory 內產生 `bin` 資料夾,裡面會有 `lrb` `lrx` `lrz` `lsb` `lsx` `lsz` 這幾個檔案:
```shell
cpt1020@Ubuntu: ~/lrzsz/bin $ ls
lrb lrx lrz lsb lsx lsz
cpt1020@Ubuntu: ~/lrzsz/bin $ ls -l
total 528
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrb
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrx
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrz
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsb
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsx
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsz
cpt1020@Ubuntu: ~/lrzsz/bin $ file lrz
lrz: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=00e89ed6a1dd2fb028bc2031738cfb3ab3fc8136, for GNU/Linux 3.7.0, not stripped
```
- 用 `file` 指令去查看這幾個執行檔,可以看到是執行在 ARM 架構 64 bit 電腦的執行檔。
8. 將 `lrb` `lrx` `lrz` `lsb` `lsx` `lsz` 這幾個檔案移到開發板的 `/usr/bin/` 裡面
![image](https://hackmd.io/_uploads/Bk5Rja0D0.png)
9. 如果要幫不同架構的開發板 Cross Compile,則可用以下指令將一些跟 configure 有關的檔案清掉,之後再幫不同架構的電腦做 Cross Compile:
```shell
$ make distclean
```
## 測試從 Host 傳檔案到開發板
1. 我在 Host 的 `~/Espressobin` 資料夾裡面有一個 `file_from_host.txt` 的檔案,想把他傳到開發板。
![image](https://hackmd.io/_uploads/ry8fq6CwR.png)
2. 先確認一下我的開發板的 `~/test_lrzsz` 資料夾裡面目前都沒有東西,然後輸入以下指令:
```shell
$ lrz
```
![image](https://hackmd.io/_uploads/SkU4qTRw0.png)
3. 這時按 `Ctrl` + `a`,然後再按 `s`,會出現一個選單(如下圖),選 `zmodem`:
![image](https://hackmd.io/_uploads/rkKS9p0P0.png)
4. 接下來就會問你要把 `/home/cpt1020/Espressobin` 資料夾內的哪個檔案傳送到開發板。將 Cursor 移動到想傳送的檔案,然後按 `space`,再按 `enter`,就會開始傳送檔案。
![image](https://hackmd.io/_uploads/HkkPqTRwA.png)
5. 檔案傳送完畢~
![image](https://hackmd.io/_uploads/rJB_5TAP0.png)
6. 檢查確認有收到 `file_from_host.txt`~!^_^
![image](https://hackmd.io/_uploads/H1Pi960DC.png)
## 測試從開發板傳檔案到 Host
1. 想要將開發板的 `~/test_lrzsz` 內的 `file_from_espressobin.c` 傳送到 Host
![image](https://hackmd.io/_uploads/HkNqtaAP0.png)
2. 用以下指令傳送檔案到 Host:
```shell!
$ lsz <filename>
```
3. 傳送完畢~!
![image](https://hackmd.io/_uploads/rym3t6CP0.png)
4. 確認 Host 的 `~/Espressobin` 資料夾內真的有收到這個檔案 😇
![image](https://hackmd.io/_uploads/HkApY6AwC.png)
## `rz`/`sz` vs `lrz`/`lsz` 🤔
一開始在查 `lrzsz` 的設定時,有的教學文是用 `rz/sz`,有的是用 `lrz/lsz`,不知道這兩者到底有什麼差別 🤔
而且像我從 Ubuntu 倉儲安裝的 `lrzsz` 是用 `rz/sz`,但我從作者提供的安裝包安裝的卻是 `lrz/lsz`。
之後去問 ChatGPT 大神,才知道 `rz/sz` 跟 `lrz/lsz` 是一樣的東西。最一開始是 `rz/sz`,之後才有 `lrz/lsz`,那個 `l` 是特別指 Linux 的意思。
<!-- ![image](https://hackmd.io/_uploads/SyFAtLF8C.png) -->
<!-- ![image](https://hackmd.io/_uploads/Hk2YmsivR.png) -->
<!-- ![image](https://hackmd.io/_uploads/SJBd5noD0.png) -->
<!-- ![image](https://hackmd.io/_uploads/Bk3bsnsD0.png) -->
<!-- ![image](https://hackmd.io/_uploads/SyPDsnivR.png) -->
<!-- ![image](https://hackmd.io/_uploads/Bkutj3swA.png) -->
<!-- ![image](https://hackmd.io/_uploads/rJEosniDC.png) -->
<!-- ![image](https://hackmd.io/_uploads/HkZ6s2svA.png) -->
<!-- ![image](https://hackmd.io/_uploads/Bkm0jniw0.png) -->
<!-- ![image](https://hackmd.io/_uploads/BkZ24-awR.png) -->
<!-- ![image](https://hackmd.io/_uploads/ByzOFT0P0.png) -->
<!-- ![image](https://hackmd.io/_uploads/HypMnnsPR.png) -->
<!-- ![image](https://hackmd.io/_uploads/S1Vuh2sP0.png) -->
<!-- ![image](https://hackmd.io/_uploads/SJ3I23owC.png) -->
<!--
```shell
$ CC=aarch64-linux-gnu-gcc CFLAGS="-O2" ./configure --prefix=/home/cpt1020/Downloads/
loading cache ./config.cache
checking for a BSD compatible install... (cached) /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... (cached) yes
checking for working aclocal... found
checking for working autoconf... found
checking for working automake... found
checking for working autoheader... found
checking for working makeinfo... missing
checking for gcc... (cached) aarch64-linux-gnu-gcc
checking whether the C compiler (aarch64-linux-gnu-gcc -O2 ) works... yes
checking whether the C compiler (aarch64-linux-gnu-gcc -O2 ) is a cross-compiler... yes
checking whether we are using GNU C... (cached) yes
checking whether aarch64-linux-gnu-gcc accepts -g... (cached) yes
checking how to run the C preprocessor... (cached) aarch64-linux-gnu-gcc -E
checking whether aarch64-linux-gnu-gcc needs -traditional... (cached) no
checking for ranlib... (cached) ranlib
checking for POSIXized ISC... no
checking for AIX... no
checking for minix/config.h... (cached) no
checking for aarch64-linux-gnu-gcc option to accept ANSI C... (cached) none needed
checking for function prototypes... yes
checking for working const... (cached) yes
checking for inline... (cached) inline
checking for syslog in -lsocket... (cached) no
checking for syslog in -lbe... (cached) no
checking for gethostbyname in -lnsl... (cached) yes
checking for ANSI C header files... (cached) yes
checking for fcntl.h... (cached) yes
checking for limits.h... (cached) yes
checking for sys/ioctl.h... (cached) yes
checking for sys/time.h... (cached) yes
checking for unistd.h... (cached) yes
checking for sys/times.h... (cached) yes
checking for termios.h... (cached) yes
checking for sys/termios.h... (cached) yes
checking for termio.h... (cached) yes
checking for sys/termio.h... (cached) no
checking for sgtty.h... (cached) yes
checking for termios.h... (cached) yes
checking for sys/termios.h... (cached) yes
checking for termio.h... (cached) yes
checking for sys/termio.h... (cached) no
checking for sgtty.h... (cached) yes
checking for sys/mman.h... (cached) yes
checking for utime.h... (cached) yes
checking for syslog.h... (cached) yes
checking for sys/syslog.h... (cached) yes
checking for sys/param.h... (cached) yes
checking for sys/select.h... (cached) yes
checking for strings.h... (cached) yes
checking for arpa/inet.h... (cached) yes
checking for size_t... (cached) yes
checking for mode_t... (cached) yes
checking for off_t... (cached) yes
checking for speed_t... (cached) yes
checking for st_rdev in struct stat... (cached) yes
checking whether time.h and sys/time.h may both be included... (cached) yes
checking for socklen_t... (cached) yes
checking whether sys/time.h and sys/select.h may both be included... (cached) yes
checking whether struct tm is in sys/time.h or time.h... (cached) time.h
checking for errno declaration... (cached) yes
checking return type of signal handlers... (cached) void
checking for unistd.h... (cached) yes
checking for getpagesize... (cached) yes
checking for working mmap... (cached) no
checking for working alloca.h... (cached) yes
checking for alloca... (cached) yes
checking for gettimeofday... (cached) yes
checking for settimeofday... (cached) yes
checking for strchr... (cached) yes
checking for memcpy... (cached) yes
checking for select... (cached) yes
checking for vprintf... (cached) yes
checking for times... (cached) yes
checking for rdchk... (cached) no
checking for utime... (cached) yes
checking for syslog... (cached) yes
checking for siginterrupt... (cached) yes
checking for mkdir... (cached) yes
checking for mktime... (cached) yes
checking for strerror... (cached) yes
checking for strstr... (cached) yes
checking for strdup... (cached) yes
checking for strtoul... (cached) yes
checking for strtol... (cached) yes
checking for strpbrk... (cached) yes
checking for stpcpy... (cached) yes
checking for strftime... (cached) yes
checking for vasprintf... (cached) yes
checking for getopt_long... (cached) yes
checking for ftime... (cached) yes
checking that ftime works correctly... (cached) will check at run time
checking for timezone variable... (cached) yes
checking for LOG_UUCP... (cached) yes
checking for argz.h... (cached) yes
checking for limits.h... (cached) yes
checking for locale.h... (cached) yes
checking for nl_types.h... (cached) yes
checking for malloc.h... (cached) yes
checking for string.h... (cached) yes
checking for unistd.h... (cached) yes
checking for sys/param.h... (cached) yes
checking for getcwd... (cached) yes
checking for munmap... (cached) yes
checking for putenv... (cached) yes
checking for setenv... (cached) yes
checking for setlocale... (cached) yes
checking for strchr... (cached) yes
checking for strcasecmp... (cached) yes
checking for strdup... (cached) yes
checking for __argz_count... (cached) yes
checking for __argz_stringify... (cached) yes
checking for __argz_next... (cached) yes
checking for LC_MESSAGES... (cached) yes
checking whether NLS is requested... yes
checking whether included gettext is requested... no
checking for libintl.h... (cached) yes
checking for gettext in libc... (cached) yes
checking for msgfmt... (cached) /usr/bin/msgfmt
checking for dcgettext... (cached) yes
checking for gmsgfmt... (cached) /usr/bin/msgfmt
checking for xgettext... (cached) /usr/bin/xgettext
checking for catalogs to be installed... de
creating ./config.status
creating Makefile
creating intl/Makefile
creating lib/Makefile
creating testsuite/Makefile
creating man/Makefile
creating po/Makefile.in
creating src/Makefile
creating Specfile
creating systype
creating src/lrzszbug
creating config.h
config.h is unchanged
$ make install
cpt1020@Ubuntu: ~/Downloads/lrzsz-0.12.21rc $ ls ~/Downloads [23:24:14]
bin Linux_Week5_Lab Linux_Week5_Lab.zip lrzsz-0.12.21rc lrzsz-0.12.21rc.tar.gz man share tSUDITJf.deb.part
cpt1020@Ubuntu: ~/Downloads/lrzsz-0.12.21rc $ cd ~/Downloads/bin [23:24:42]
cpt1020@Ubuntu: ~/Downloads/bin $ ls [23:24:54]
lrb lrx lrz lsb lsx lsz
cpt1020@Ubuntu: ~/Downloads/bin $ ls -l [23:24:55]
total 528
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrb
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrx
-rwxr-xr-x 3 cpt1020 cpt1020 84472 Jul 11 23:24 lrz
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsb
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsx
-rwxr-xr-x 3 cpt1020 cpt1020 94112 Jul 11 23:24 lsz
cpt1020@Ubuntu: ~/Downloads/bin $ file lrz [23:24:58]
lrz: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=00e89ed6a1dd2fb028bc2031738cfb3ab3fc8136, for GNU/Linux 3.7.0, not stripped
$ make clean
$ make distclean
cpt1020@Ubuntu: ~/Downloads/bin $ sudo cp l* /media/cpt1020/root/usr/bin [23:33:11]
cpt1020@Ubuntu: ~/Downloads/bin $ ls /media/cpt1020/root/usr/bin | grep lr [23:33:28]
colrm
cppcheck-htmlreport
lrb
lrx
lrz
```
-->
<!--
```shell
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
```
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
-->