# 使用 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. -->