# 編譯 & 安裝 OpenWRT 至 Marvell ESPRESSObin v7 開發板 由於 Marvell ESPRESSObin v7 官網介紹安裝 OpenWRT 的版本有點舊了、安裝的環境也有點舊 😵💫 所以自己研究了一下從下載 OpenWRT source code、編譯 image、到使用 SD 卡開機的過程~ ## Host Machine Host machine 是安裝在 MacBook M3 的 VirtualBox 的 Ubuntu 24.04 虛擬機: ```shell $ cat /etc/os-release PRETTY_NAME="Ubuntu 24.04.1 LTS" NAME="Ubuntu" VERSION_ID="24.04" VERSION="24.04.1 LTS (Noble Numbat)" VERSION_CODENAME=noble ID=ubuntu ID_LIKE=debian 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" UBUNTU_CODENAME=noble LOGO=ubuntu-logo ``` ## Setting Up Host Machine > Reference https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem#debianubuntumint 在 Ubuntu 的 terminal 輸入以下指令: ```shell $ sudo apt update $ sudo apt -y install build-essential clang flex bison g++ gawk \ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gettext git \ libncurses-dev libssl-dev python3-setuptools rsync swig unzip \ zlib1g-dev file wget ``` ## Configuring & Building the OpenWRT > Reference https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem 下載 OpenWRT source code: ```shell $ git clone https://git.openwrt.org/openwrt/openwrt.git $ git clone https://github.com/openwrt/openwrt.git 這個比較快 前面那個很慢 $ cd openwrt $ git pull ``` 切換到 `v23.05.5` 版本: ```shell $ git checkout v23.05.5 ``` 若想查看其他 OpenWRT 版本,可以用以下指令查看: ```shell $ git branch -a $ git tag ``` 更新 feeds: ```shell $ ./scripts/feeds update -a $ ./scripts/feeds install -a ``` Configure the firmware image: ```shell $ make menuconfig ``` - 執行完以上指令後會出現以下畫面,要針對開發板做一些設定  - `Target System` -> 勾選 `Marvell EBU Armada` 由於 Marvell ESPRESSObin v7 是 `Marvell Armada 3700LP (88F3720) dual-core ARM Cortex A53 processor`,所以這裡才勾選 `Marvell EBU Armada` https://wiki.espressobin.net/tiki-index.php?page=About+ESPRESSObin  - `Subtarget` -> 勾選 `Marvell Armada 3700LP (ARM64)`  - `Target Profile` -> 我這裡是勾選 `Marvell ESPRESSObin V7 Non-eMMC` 由於 Marvell ESPRESSObin v7 有分成有 eMMC 和無 eMMC,而我買的是 non-eMMC,所以就勾選這個選項 勾選這選項後,他也會自動勾選 `Marvell Armada 3700 Community Board V7 Non-eMMC` 這個選項  - `Target Images` 的部分,根據 Marvell ESPRESSObin v7 官網的教學,至少要勾選 `ramdisk`、`tar.gz`、和 `ext4` [https://wiki.espressobin.net/tiki-index.php?page=Build+From+Source+-+OpenWrt#Image_configuration](https://wiki.espressobin.net/tiki-index.php?page=Build+From+Source+-+OpenWrt#Image_configuration)  - 若需要使用 OpenWRT 的 LuCI Web Interface 的話,記得要到主選單的 `LuCI` -> `1. Collections` 內做設定  - 其他的部分就依照個人需求做設定~設定完之後就按 `Save`,然後 `Exit` <!--  --> 用以下指令 build firmware image: ```shell $ make -j$(nproc) defconfig download clean world V=s ``` - `-j$(nproc)`:由於 build image 會花很多時間,我們可以依據電腦有多少核心就代入 `-j` 讓 build image 的過程可以快一點 在 Ubuntu 系統輸入 `nproc` 可以直接得到電腦目前有多少核心 - `V=s`:build image 的過程可以看到詳細的資訊 :::info 之後若需要重新 build image,可能會需要把 build environment 清乾淨再重 build,針對不同的狀況有以下這些不同的指令可以用,如下截圖:  ::: https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem 官網有更多關於 build image 的細節說明~ Build 完之後,image 會出現在 `openwrt/bin/targets/mvebu/cortexa53/` 裡面,接下來會用到的是 `openwrt-mvebu-cortexa53-globalscale_espressobin-v7-ext4-sdcard.img.gz`。 <!--  -->  用以下指令解壓縮,會得到 `openwrt-mvebu-cortexa53-globalscale_espressobin-v7-ext4-sdcard.img`: ```shell $ gunzip openwrt-mvebu-cortexa53-globalscale_espressobin-v7-ext4-sdcard.img.gz ```  <!--  --> ## Flash Image to SD Card 在插入 micro SD 卡之前,先執行 `lsblk`。待 micro SD 卡插到電腦後,再執行一次 `lsblk`,從以下截圖可看到我的 micro SD 卡的裝置是 `sdb`(以下截圖上半部分是尚未插入 micro SD 卡,下半部則是插入 micro SD 卡之後):  可用以下指令確認 `/dev/` 底下是否有 `sdb`: ```shell $ ls -l /dev/ | grep sdb ```  用以下指令清空 micro SD 卡: ```shell $ sudo dd if=/dev/zero of=/dev/sdb bs=1M count=100 ``` 先 unmount 裝置的 partition(或者將 SD 卡退出再重插入電腦): ```shell $ sudo umount /dev/sdb1 ``` 建立新的 partition ```shell $ (echo n; echo p; echo 1; echo ''; echo ''; echo w) | sudo fdisk /dev/sdb ``` 可以用以下指令查看 micro SD 卡的資訊: ```shell $ sudo fdisk -l /dev/sdb ```  用以下指令將 micr SD 卡格式化成 EXT4 格式: ```shell $ sudo mkfs.ext4 -O ^metadata_csum,^64bit -L root /dev/sdb1 ``` Unmount `sdb1`: ```shell $ sudo umount /dev/sdb1 ``` 使用 `dd`(disk duplicate)工具將 image 寫入 micro SD 卡(`/dev/sdb/`)內: ```shell ~/openwrt/bin/targets/mvebu/cortexa53$ sudo dd if=openwrt-mvebu-cortexa53-globalscale_espressobin-v7-ext4-sdcard.img of=/dev/sdb bs=4M conv=fsync ``` - `if`:input file,也就是 image - `of`:output file,也就是寫入 `/dev/sdb` 內 - `bs`:block size,設定為 4 MB - `conv`:確保所有 data 都寫入後才結束,以避免 data 仍留在 cache 內 完成後將 micro SD 卡退出再重新插入電腦,Ubuntu 作業系統應該會自動將其掛載。此時用 `lsblk` 指令可看到 `sdb` 現在有兩個 parition,分別是 `sdb1` 和 `sdb2`,會分別被掛載到 `/media/<user_name>/kernel` 和 `/media/<user_name>/rootfs`:  - `/media/<user_name>/kernel` - 裡面有 `.dtb`,也就是 device tree blob,也就是編譯後的 device tree 的 binary 檔案 - 另外還有 `Image`。 - `/media/<user_name>/rootfs` - 裡面就是 root file system。  ## Configuring Uboot Environment Variable 將 micro SD 卡退出電腦,插入 Marvell ESPRESSObin v7,並用 micro USB 線連接 Marvell ESPRESSObin v7 和電腦,此時先不用給 Marvell ESPRESSObin v7 插入電源。 插入後,`/dev/` 底下應該會多出一個 `ttyUSB` 裝置,以我的例子就是 `ttyUSB0`:  用以下指令開啟 minicom: ```shell $ sudo minicom -s ``` 開啟 minicom 後會看到以下畫面:  先到 `Serial port setup` 做設定,會看到以下選單。按 `a` 會可以修改 `Serial Device`,將其修改為 `/dev/ttyUSB0`,然後按 enter;此外,也要確認 `Bps/Par/Bits` 是 `115200 8N1`  <!--  --> 修改成以下結果:  回到主選單後,可以點 `Save setup as dfl`,將目前的設定都設為預設,然後選 `Exit`,接下來就會看到以下畫面:  這時再將 Marvell ESPRESSObin v7 接上電源,就會開始有東西跑出來。在出現 `Hit any key to stop autoboot` 時,按 enter,這樣就能設定 U-boot 的環境變數: :::info 前述 `Hit any key to stop autoboot` 期間所倒數的秒數,是由 U-boot 的環境變數 `bootdelay` 所設定的,可以在進入 U-boot 後做設定。 :::  用 `ext4ls mmc 0:1` 和 `ext4ls mmc 0:2` 能分別檢視 SD 卡 partition 1 和 partition 2 有什麼東西 - `ext4ls`:列出 ext4 file system 內的檔案,相當於 `ls` 指令 - `mmc`:eMMC 或 SD 卡 - `0`:第一個 MMC 裝置(通常是 eMMC 或 SD 卡) - `1`/`2`:該裝置的第二個 partition - 第一個 partition 就是前面看到會被掛載到 `/media/<user_name>/kernel` 的部份 - 第二個 partition 則是會被掛載到 `/media/<user_name>/rootfs`   接下來設定以下環境變數: ```uboot Marvell>> setenv image_name Image Marvell>> setenv fdt_name armada-3720-espressobin-v7.dtb Marvell>> setenv bootcmd 'mmc dev 0; \ ext4load mmc 0:1 $kernel_addr_r $image_name; \ ext4load mmc 0:1 $fdt_addr_r $fdt_name; \ setenv bootargs $console root=/dev/mmcblk0p2 rw rootwait; \ booti $kernel_addr_r - $fdt_addr_r' Marvell>> saveenv ``` :::info 其中最長的那個指令: - U-Boot 使用 `bootcmd` 環境變數作為開機的指令,所以第三個指令的那一大串就是開機時要執行的指令 - `bootcmd` 的內容通常會包含: 1. 設定開機的 device 2. 載入 linux kernel 3. 設定 kernel 參數 4. 執行 kernel - `mmc dev 0`:將 MMC 0 作為開機的 device - `ext4load mmc 0:1 $kernel_addr_r $image_name` - 從 MMC device 0 的 partition 1 讀取 Linux Kernel image(名稱由 `$image_name` 指定),並將其載入到 RAM 的 `$kernel_addr_r` 位置。 - `ext4load mmc 0:1 $fdt_addr_r $fdt_name` - 從 MMC device 0 的 partition 1 讀取 Device Tree Binary(名稱由 `$fdt_name` 指定),並將其載入到 RAM 的 `$fdt_addr_r` 位置。 - `setenv bootargs $console root=/dev/mmcblk0p2 rw rootwait` - 這裡在設定 kernel 的啟動參數 `bootargs` Command line arguments passed when booting an operating system or binary image - `$console`:指定控制台裝置。 - `$console` 被設定為 `console=console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000` - `root=/dev/mmcblk0p2`:將 rootfs 指定為 `mmcblk0p2`(即 MMC device 的 partition 2)。 - `rw`:讓 rootfs 以 read-write 模式掛載,讓我們可以讀寫。 - `rootwait`:等待 rootfs 可用,避免發生找不到 rootfs 的錯誤。 - `booti $kernel_addr_r - $fdt_addr_r` - `booti` 是 U-Boot 的一個指令,用來啟動 Image 格式的 Linux kernel ```uboot booti [<addr> [<initrd>[:<size>]] [<fdt>]] ``` - `<addr>`:Kernel image 的記憶體位址 - `<initrd>`:initrd/initramfs 的記憶體位址(如果沒有,填 `-`,不影響開機) address of the initial RAM disk. Use `-` to boot a kernel with a device tree but without an initial RAM disk. - `<size>`:size of the initial RAM disk. This parameter must be specified for raw initial RAM disks. - `<fdt>`:Device Tree Blob (DTB) 的記憶體位址 - https://docs.u-boot.org/en/v2021.04/usage/booti.html ::: :::success 以下是完整的環境變數設定: ```uboot Marvell>> printenv arch=arm baudrate=115200 board=mvebu_armada-37xx board_name=mvebu_armada-37xx bootargs=console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 root=/dev/mmcblk0p1 rw rootwait bootcmd=mmc dev 0; \ ext4load mmc 0:1 $kernel_addr_r $image_name; \ ext4load mmc 0:1 $fdt_addr_r $fdt_name; \ setenv bootargs $console root=/dev/mmcblk0p2 rw rootwait; \ booti $kernel_addr_r - $fdt_addr_r bootdelay=2 bootmmc=mmc dev 0; ext4load mmc 0:1 $kernel_addr $image_name;setenv bootargs $console root=/dev/mmcblk0p1 rw rootwait; booti $kernel_addr - $fdt r console=console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 cpu=armv8 eth1addr=00:51:82:11:22:01 ethact=neta@30000 ethaddr=F0:AD:4E:2C:33:AD ethprime=eth0 extra_params=pci=pcie_bus_safe fdt_addr_r=0x6f00000 fdt_high=0xffffffffffffffff fdt_name=armada-3720-espressobin-v7.dtb fdtcontroladdr=3f62a450 fileaddr=7000000 filesize=13a3200 gatewayip=10.4.50.254 get_images=tftpboot $kernel_addr_r $image_name; tftpboot $fdt_addr_r $fdt_name; run get_ramfs get_ramfs=if test "${ramfs_name}" != "-"; then setenv ramdisk_addr_r 0x8000000; tftpboot $ramdisk_addr_r $ramfs_name; else setenv ramdisk_addr_r i hostname=marvell image_name=Image initrd_addr=0xa00000 initrd_size=0x2000000 ipaddr=0.0.0.0 kernel_addr_r=0x7000000 loadaddr=0x6000000 netdev=eth0 netmask=255.255.255.0 pcb_rev=7.3.4 pcb_sn=BUD-2252-000194 ramdisk_addr_r=0x8000000 ramfs_name=- root=root=/dev/nfs rw rootpath=/srv/nfs/ serverip=0.0.0.0 set_bootargs=setenv bootargs $console soc=mvebu stderr=serial@12000 stdin=serial@12000 stdout=serial@12000 vendor=Marvell Environment size: 1658/65532 bytes ``` ::: <!-- :::info 在 U-Boot 下,有幾種不同的 Kernel 啟動方式: bootm:用來啟動 uImage 格式的 Kernel(通常是 mkimage 轉換過的)。 bootz:用來啟動 zImage 格式的 Kernel(適用於 32-bit ARM)。 booti:用來啟動 AArch64 (ARM 64-bit) 的 Image 格式 Kernel(未壓縮的 Image)。 所以 booti 是專門用來啟動 ARM 64-bit Linux Kernel,而且不支援 uImage 或 zImage,只能用 Image 格式。  ::: --> 最後,用 `reset` 或 `run bootcmd` 應該就可以順利用 micro SD 卡開機啦~  :::warning 我在開機的時候他畫面會突然一直停在以下畫面,但只要按 enter 就好了~  ::: 若要退出 minicom: - Ubuntu:先按 `ctrl` + `a`,放掉後按 `z`,再按 `x` 即可退出。 - macOS:先按 `esc` + `z`,放掉後按 `x` 即可退出。 ## OpenWRT LuCI Web Interface 用網路線將 Marvell ESPRESSObin v7 的 LAN port 跟電腦連接,而預設的網頁 IP 是 `192.168.1.1`,所以就在瀏覽器內輸入 `192.168.1.1`(`http://192.168.1.1/cgi-bin/luci/`)即可存取 LuCI Web Interface:  (我在前面 `make menuconfig` 有選到 LuCI 其他 theme,所以顯示出來的畫面不是傳統的 OpenWRT LuCI 畫面) :::info 若依前面的設定,編譯出來的 OpenWRT image 應該會有 DHCP server 的功能,所以只要用網路線將 Marvell ESPRESSObin v7 的 LAN port 跟電腦連接,那 Marvell ESPRESSObin v7 的 DHCP server 就會 assign 一個 `192.168.1.xxx` 的 IP 給電腦。 ::: 若依照前面的步驟設定,Username 是 `root`,Password 是空白,直接點 `Log in` 即可。 <!-- 若要修改 LuCI Web Interface 的 IP,像是修改成 `192.168.60.1`,那就對開發板做以下設定: ```shell root@OpenWrt:~# uci set network.lan.ipaddr=192.168.60.1 root@OpenWrt:~# uci commit network.lan root@OpenWrt:~# /etc/init.d/network restart ``` 也要將電腦的 IP 設定成 `192.168.60.xx` 的 IP,看是用 DHCP 取得或手動設置 static IP,之後再開啟瀏覽器輸入 `192.168.60.1` 即可。 像是若是 MacBook 就到 `System Settings` -> `Network` -> 點選該 interface,以我的例子就如下圖中的 `USB 10/100/1000 LAN` -> 點 `Details` -> 然後做如下截圖的設定~    --> <!-- ## 讓 VirtualBox 的 Ubuntu 虛擬機經由開發板分配 IP  這時用 `ifconfig` 就會多出 `enp0s9` 這個 interface,且也取得 `192.168.60.x` 的 IP 了  -->
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up