---
# System prepended metadata

title: 【embeded_linux】透過網路建立交叉編譯環境
tags: [Embedded_linux]

---

<style>
table {
  word-break: normal !important;
}
</style>
:::info
 **實驗目標**: 透過tftp 載入kernel 和DTB，利用nfs掛載rootfs
 **實驗目的**:方便嵌入式開發和除錯
 **實驗器材**:正點原子STM32MP157 Mini開發板、筆電、 USB Type-C 轉 RJ45 Gigabit網路卡
:::

## 1.設置網路IP
![image](https://hackmd.io/_uploads/ByqPc0ngJg.png)
> - 透過VMware 模擬一個基於x86環境下的ubuntu建立交叉工具鏈
> - ubuntu環境IP設置為192.168.0.12
> - 開發版環境IP設置為192.168.0.8
> - 橋接網卡 IP 設置為192.168.0.10
## 三者互ping
| 項目                    | 圖片                                                     |
|-------------------------|----------------------------------------------------------|
| win pin ubuntu          | ![image](https://hackmd.io/_uploads/HJDQKseWyg.png)      |
| win pin 開發版          | ![image](https://hackmd.io/_uploads/rknPFsxWJx.png)      |
| ubuntu pin 開發版       | ![image](https://hackmd.io/_uploads/rkY5FolbJg.png)      |
| ubuntu pin windows      | ![image](https://hackmd.io/_uploads/ryT85oeZkx.png)      |
| 開發版 pin ubuntu       | ![image](https://hackmd.io/_uploads/BJf-colW1x.png)      |

:::warning
這裡還需要在主機端配置tftp和nfs ，這裡可以參考正點原子提供的官方鏡像，這裡就先省略
:::
## 在uboot 環境下設置環境變數
```javascript
setenv ipaddr 192.168.0.8 
setenv ethaddr b8:ae:1d:01:01:00 
setenv gatewayip 192.168.0.1 
setenv netmask 255.255.255.0 
setenv serverip 192.168.0.12  
```
:::success
uboot 中有兩個重要的環境變數：bootcmd 和 bootargs，設定後保存在 emmc 中。

- bootcmd ：主要作用是`儲存啟動指令`。
          例如：下載核心、裝置樹 到 記憶體中，再啟動 Linux 。
          uboot 啟動倒數結束後、會預設執行 bootcmd 變數。

- bootargs：保存著`傳遞給核心的參數`。
:::

## 設定 bootcmd

```shell
setenv bootcmd 'tftp c2000000 uImage;tftp c4000000 stm32mp157d-atk.dtb;bootm c2000000 - c4000000'
```
以下是對這行命令的解釋，

```shell
setenv bootcmd 'tftp c2000000 uImage;tftp c4000000 stm32mp157d-atk.dtb;bootm c2000000 - c4000000'
```

### 分解解釋：

- **`setenv bootcmd`**：設定環境變量 `bootcmd`，這是 U-Boot 的一個命令，用於定義開機時執行的預設指令。

- **`tftp c2000000 uImage;`**
  - **`tftp`**：透過 TFTP（Trivial File Transfer Protocol）從網路下載文件。
  - **`c2000000`**：這是下載 `uImage` 的內存地址。`c2000000` 是一個內存地址，用於指定下載的 `uImage` 應放置的地方。
  - **`uImage`**：這是 Linux 核心映像文件。

- **`tftp c4000000 stm32mp157d-atk.dtb;`**
  - **`tftp`**：同樣透過 TFTP下載文件。
  - **`c4000000`**：這是下載 `stm32mp157d-atk.dtb` 的內存地址。`c4000000` 表示將這個裝置樹（Device Tree Blob）文件存儲在指定的內存位置。
  - **`stm32mp157d-atk.dtb`**：這是設備樹文件，用於告訴 Linux 核心有關特定硬體的詳細信息。

- **`bootm c2000000 - c4000000`**
  - **`bootm`**：啟動命令，用於啟動 Linux 核心。
  
  - **`c2000000`**：指定核心映像 (`uImage`) 的內存地址，這是先前下載的 `uImage` 所在位置。
  - **`-`**：這個位置留空（表示不需要 ramdisk）。
  - **`c4000000`**：指定設備樹文件 (`stm32mp157d-atk.dtb`) 的內存地址，這是先前下載的設備樹文件所在位置。

### 總結
這行指令設定了 `bootcmd`，在開機時會執行以下步驟：
1. 使用 TFTP 下載 Linux 核心映像 `uImage`，並將其放置在內存地址 `c2000000`。
2. 使用 TFTP 下載設備樹文件 `stm32mp157d-atk.dtb`，並將其放置在內存地址 `c4000000`。
3. 使用 `bootm` 命令啟動 Linux 核心，指定內存地址 `c2000000` 作為核心映像地址，以及 `c4000000` 作為設備樹文件地址。

這一行命令的作用是從 TFTP 伺服器下載所需的核心映像和設備樹文件，並啟動它們。
## 設定 bootargs
```shell
setenv bootargs 'console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.0.12:/home/alientek/linux/nfs/rootfs,proto=tcp rw ip=192.168.0.8:192.168.0.12:192.168.0.1:255.255.255.0:eth0::off'
```
:angry::angry::angry::angry::angry::angry::angry::angry::angry::angry::angry:
:::danger
 這邊非常容易出錯，多一個空格，多按到enter鍵，少一個冒號: 開機都會失敗
具體請按照底下格式。
![image](https://hackmd.io/_uploads/BJ_7jj2bye.png)

:::

### 分解解釋：

- **`setenv bootargs`**：設定環境變量 `bootargs`，這是 U-Boot 的一個參數，用於傳遞啟動引數給 Linux 核心。

- **`console=ttySTM0,115200`**
  - **`console=ttySTM0`**：指定控制台的輸出設備為 `ttySTM0`，這是串口終端（通常是串口設備）。
  - **`115200`**：設置串口的波特率為 115200，這是常見的串口通信速率。

- **`root=/dev/nfs`**
  - **`root=/dev/nfs`**：指定根文件系統的設備為 NFS（網路文件系統）。這表示根文件系統將透過網路進行掛載，而不是使用本地的存儲設備。

- **`nfsroot=192.168.0.12:/home/alientek/linux/nfs/rootfs,proto=tcp`**
  - **`nfsroot`**：指定 NFS 的根文件系統位置。
  - **`192.168.0.12:/home/alientek/linux/nfs/rootfs`**：這是 NFS 伺服器的 IP 位址（`192.168.0.12`）和根文件系統的路徑 (`/home/alientek/linux/nfs/rootfs`)。
  - **`proto=tcp`**：使用 TCP 協議來傳輸 NFS 數據，比 UDP 更穩定，適合需要穩定連接的場景。

- **`rw`**：設置根文件系統為可讀寫模式。這意味著系統可以對根文件系統進行讀寫操作。

- **`ip=192.168.0.8:192.168.0.12:192.168.0.1:255.255.255.0:eth0::off`**
  - **`ip`**：設置網路配置參數。
  - **`192.168.0.8`**：設備的 IP 位址。
  - **`192.168.0.12`**：NFS 伺服器的 IP 位址。
  - **`192.168.0.1`**：網關的 IP 位址。
  - **`255.255.255.0`**：子網遮罩。
  - **`eth0`**：網卡接口名稱，指定使用 `eth0` 作為網絡接口。
  - **`::off`**：停用 BOOTP/DHCP，自定義的靜態 IP 設置。

### 總結
這行命令用於設定 Linux 核心的啟動引數，目的是：

1. 設置控制台的串口參數。
2. 指定使用 NFS 來掛載根文件系統，並提供 NFS 伺服器的位置及協議。
3. 配置根文件系統為可讀寫模式。
4. 設置網絡參數（包括設備 IP、NFS 伺服器 IP、網關、子網遮罩等）以支持網路啟動。
## 儲存環境變數
```shell
saveenv
```

## 開機
> 這個命令可能在其他開發版會有不同
```shell
boot
```
## 開機結果 
[連結](https://drive.google.com/file/d/1IdsZjmhf9PUAwlYK9KYUBqi37C9e9K3y/view?usp=sharing)


