14 Ethernet
1 Ethernet Introduction
1.1 Introduction to RK3568 Network Card
When mentioning networking, many friends must have heard the term "network card". In the past, if computers needed to go online, they had to buy a network card and insert it, just like today's discrete graphics desktops. The reason is that with the continuous development of technology, now only one chip is needed to implement the wired network card function. Therefore, network card chips are directly placed on the motherboard (generally speaking, following the network cable interface).
Embedded network hardware is divided into two parts: MAC and PHY. Some SoCs claim to support networking, which means they have integrated network MAC peripherals. Common general SoCs generally integrate network MAC peripherals, such as RK series, I.MX series, STM32MP1 series, etc. The advantage of integration is that it can significantly improve network speed (such as using network-specific DMA), support 10/100/1000M network speed, and only need to connect an external PHY chip. (If MAC peripheral is not integrated, most use integrated MAC+PHY network chips). MAC connects to external PHY chips through MII/RMII interface or GMII/RGMII interface to complete network data transmission.
RK3568 kernel integrates two 10M/100M/1000M network MACs, complying with IEEE802.3-2002 standard. The MAC layer supports full-duplex or half-duplex operation programmable, with a. The MAC is dedicated DMA with direct memory interface, formats data into packets complying with IEEE802.3-2002 standard, and transmits these data to the Ethernet physical interface (PHY). It can also move packets from RXFIFO to microprocessor memory. The main features of RK3568's internal ENET peripheral are as follows:
- ①, Supports full-duplex and half-duplex operation.
- ②, Full-duplex flow control operation (IEEE 802.3X pause packets and priority flow control)
- ③, Header and frame start data (SFD) are automatically inserted in transmit mode, automatically deleted in receive.
- ④, CRC and pad auto-generation can be controlled frame by frame
- ⑤, Programmable packet length, supports standard Ethernet packets or giant Ethernet packets up to 16KB
- ⑥, Programmable packet gap
- ⑦, Two groups of FIFO: one 4096-byte transmit FIFO with programmable threshold function and one 4096-byte receive FIFO with configurable threshold function
1.2 Basic Introduction to IP Address, Subnet Mask, Default Gateway, DNS Server
For computers to achieve network communication, they must have a network address for quick positioning. IP is 32-bit binary data, usually expressed in decimal and separated by ".". IP address is the unique identity ID of a computer in the network. Just like express delivery needs a specific residential address in the real world, IP address = network address + host address (also known as: host number and network number)
So how to distinguish between network address and host address in an IP address? This requires the subnet mask. When the value of the subnet mask is 255, the corresponding bit of the IP address is the network address bit. For example, IP address: 192.168.22.88, subnet mask is 255.255.255.0, then 192.168.22 is the network address. The network address is used to determine which LAN you are in, such as finding your home or company's network. The host address is used to determine your position within the LAN. For example, 192.168.22.88 is the network IP of your living room TV, and 192.168.22.66 is the network IP of your home computer. When the network is disconnected, devices in the LAN can communicate with each other. For example, after a phone connects to the router's network, you can enter the IP to access its backend for management.
The gateway can be understood as a tool to send data from the LAN to the outside. The specific parsing process is not introduced here.
Since IP addresses are hard to remember, we usually input a website address when browsing the internet, such as "baidu.com". The function of DNS is to map this website name to the IP address, so you can enter the website to access the corresponding IP server.
2 Ethernet Board Card Interface

3 Ethernet Usage - Command Line Method
3.1 Device Tree Parsing
Tips
The file path below: out/kernel/src_tmp/linux-5.10/arch/arm64/boot/dts/rockchip Need to compile the source code first.
In this project, the configuration of Ethernet nodes follows the three-layer structure of the device tree as follows:
Basic definition layer, taking gmac0 as an example (rk3568.dtsi):
gmac0: ethernet@fe2a0000 {
compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a";
reg = <0x0 0xfe2a0000 0x0 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq", "eth_wake_irq";
rockchip,grf = <&grf>;
clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>,
<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>,
<&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>,
<&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>,
<&cru PCLK_XPCS>;
clock-names = "stmmaceth", "mac_clk_rx",
"mac_clk_tx", "clk_mac_refout",
"aclk_mac", "pclk_mac",
"clk_mac_speed", "ptp_ref",
"pclk_xpcs";
resets = <&cru SRST_A_GMAC0>;
reset-names = "stmmaceth";
snps,mixed-burst;
snps,tso;
status = "disabled";
mdio0: mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <0x1>;
#size-cells = <0x0>;
};
};compatible: Specifies compatibility, supports RK3568 GMAC and standard DWC Ethernet MAC 4.20areg: Register address range (0xfe2a0000-0xfe2affff)interrupts: MAC interrupt number 27 and wake interrupt number 24, both high-level triggeredclocks: Contains 9 clock sources, covering MAC core clock, RX/TX clock, reference clock, etc.snps,mixed-burst: Enable mixed burst transfer modesnps,tso: Enable TCP segmentation offload functionmdio0: Built-in MDIO bus controller for PHY managementstatus: Default disabled state
Pin configuration layer (rk3568-pinctrl.dtsi):
//GMAC0 RGMII mode pin configuration:
gmac0_miim: gmac0-miim {
rockchip,pins =
/* gmac0_mdc */
<2 RK_PC3 2 &pcfg_pull_none>,
/* gmac0_mdio */
<2 RK_PC4 2 &pcfg_pull_none>;
};
gmac0_rgmii_clk: gmac0-rgmii-clk {
rockchip,pins =
/* gmac0_rxclk */
<2 RK_PA5 2 &pcfg_pull_none>,
/* gmac0_txclk */
<2 RK_PB0 2 &pcfg_pull_none_drv_level_1>;
};
gmac0_rgmii_bus: gmac0-rgmii-bus {
rockchip,pins =
/* gmac0_rxd2 */
<2 RK_PA3 2 &pcfg_pull_none>,
/* gmac0_rxd3 */
<2 RK_PA4 2 &pcfg_pull_none>,
/* gmac0_txd2 */
<2 RK_PA6 2 &pcfg_pull_none_drv_level_2>,
/* gmac0_txd3 */
<2 RK_PA7 2 &pcfg_pull_none_drv_level_2>;
};
gmac0_tx_bus2: gmac0-tx-bus2 {
rockchip,pins =
/* gmac0_txd0 */
<2 RK_PB3 1 &pcfg_pull_none_drv_level_2>,
/* gmac0_txd1 */
<2 RK_PB4 1 &pcfg_pull_none_drv_level_2>,
/* gmac0_txen */
<2 RK_PB5 1 &pcfg_pull_none>;
};
...........
//GMAC1 provides two pin configuration modes:
/* M0 mode - uses GPIO3 group */
gmac1m0_rgmii_clk: gmac1m0-rgmii-clk {
rockchip,pins =
/* gmac1_rxclkm0 */
<3 RK_PA7 3 &pcfg_pull_none>,
/* gmac1_txclkm0 */
<3 RK_PA6 3 &pcfg_pull_none_drv_level_1>;
};
/* M1 mode - uses GPIO4 group */
gmac1m1_miim: gmac1m1-miim {
rockchip,pins =
/* gmac1_mdcm1 */
<4 RK_PB6 3 &pcfg_pull_none>,
/* gmac1_mdiom1 */
<4 RK_PB7 3 &pcfg_pull_none>;
};gmac0: Uses GPIO2 group pins, supports RGMII Gigabit Ethernetgmac1m0: Uses GPIO3 group pins, suitable for single network port designgmac1m1: Uses GPIO4 group pins, suitable for dual network port design
Finally, let's look at the board-level configuration layer (rk3568-toybrick-x0.dtsi):
&gmac0 {
phy-mode = "rgmii";
clock_in_out = "output";
snps,reset-gpio = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
snps,reset-delays-us = <0 20000 100000>;
assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>;
assigned-clock-rates = <0>, <125000000>;
pinctrl-names = "default";
pinctrl-0 = <&gmac0_miim
&gmac0_tx_bus2
&gmac0_rx_bus2
&gmac0_rgmii_clk
&gmac0_rgmii_bus>;
tx_delay = <0x2d>;
rx_delay = <0x13>;
phy-handle = <&rgmii_phy0>;
status = "okay";
};
&mdio0 {
rgmii_phy0: phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x0>;
};
};&gmac0: References the gmac0 node from the basic definitionphy-mode = "rgmii": Configured as RGMII Gigabit Ethernet modeclock_in_out = "output": Clock output modesnps,reset-gpio: PHY reset pin uses GPIO2_D3, low level activesnps,reset-delays-us: Reset timing: 0ms pre-delay, 20ms reset duration, 100ms post-reset delayassigned-clock-rates: Sets GMAC clock frequency to 125MHz- tx_delay/rx_delay: RGMII interface transmit/receive delay compensation
phy-handle: Associates with rgmii_phy0 PHY devicergmii_phy0: IEEE 802.3 standard compatible PHY chip, MDIO address is 0
3.2 Application Layer Testing Network Methods
On the development board, you can use the following common commands to test the network (note: x.x.x.x is the network card address):
ifconfig # View network interfaces in the device
ping x.x.x.x # Test if the network is normal by exchanging packets with a specific network
ifconfig eth0 X.X.X.X up # Enable network
ifconfig eth0 X.X.X.X down # Disable network3.3 Specific Demonstration of Network Testing Function
We take Ethernet interface 1 as an example and connect the network cable for testing:

After plugging in, enter the command ifconfig in the terminal to view the network port information:

The system successfully recognizes two Ethernet interfaces. You can see that the interface with the network cable inserted is assigned a network IP, and the broadcast address, subnet mask, and other information are displayed.
Now enter the command ping baidu.com to test the network connection:

Three groups of data were sent, no packet loss. At this point, the system can successfully connect to Ethernet.
4. Ethernet Usage - Official Library Method
Data Path
hap package: /05-Development-Materials/01-OpenHarmony-Development-Materials/Peripheral-Test-APP/HAP/NET_TEST.hap
Source code: /05-Development-Materials/01-OpenHarmony-Development-Materials/Peripheral-Test-APP/SRC/NATEWORK_TEST
We have also written a network test example here, but it uses the official network library @kit.NetworkKit. Essentially it is also NAPI, but OpenHarmony officials have already encapsulated it for us, so we just need to call it.
Since OpenHarmony's official ArkTS network library is sufficient for our network development needs. This time we use the built-in network library for writing, which can greatly improve our development speed and also expand a development method for everyone!
4-1 Test APP Implementation Effect
Let's look at the effect of the test APP implementation:
The first column will display the network connection status, connection type, and local IP address

Click network test, it will send an HTTP request to test the network

Below is an introduction to several related functions involved:
4.2 Network Related API Function Introduction
1. connection.getDefaultNet()
- Function: Get the default network connection handle of the current device
- Return value:
NetHandleobject (representing active network connection)
2. connection.getNetCapabilities(netHandle)
- Function: Get network capability information
- Return value:
bearerTypes: Network bearer type array
3. connection.getConnectionProperties(netHandle)
- Function: Get network connection properties
4. http.createHttp()
- Function: Create HTTP request object
5. httpRequest.request(url, options)
- Function: Send HTTP request
6. httpRequest.destroy()
- Function: Destroy HTTP request object
4.3 Network Test APP Code Implementation
Here is the ets code for friends who need to study:
import { hilog } from '@kit.PerformanceAnalysisKit';
import { connection } from '@kit.NetworkKit';
import { socket } from '@kit.NetworkKit';
import { http } from '@kit.NetworkKit';
const DOMAIN = 0x0000;
@Entry
@Component
struct Index {
@State currentIpAddress: string = 'Getting...';
@State networkMessage: string = 'Network Test Ready';
@State networkResult: string = '';
@State isNetworkLoading: boolean = false;
@State targetHost: string = 'www.baidu.com';
@State connectionType: string = 'Unknown';
@State isConnected: boolean = false;
build() {
Row() {
Column() {
Text('ShiMate Pi')
.fontSize(40)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('Network Information & Test')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
// Network status information card
Column() {
Text('Network Status Information')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
Row() {
Text('Connection Status: ')
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text(this.isConnected ? 'Connected' : 'Disconnected')
.fontSize(18)
.fontColor(this.isConnected ? Color.Green : Color.Red)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 10 })
Row() {
Text('Connection Type: ')
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text(this.connectionType)
.fontSize(18)
.fontColor(Color.Blue)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 10 })
Row() {
Text('Local IP Address: ')
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text(this.currentIpAddress)
.fontSize(18)
.fontColor(Color.Blue)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 15 })
Button('Refresh Network Info')
.fontSize(16)
.width('100%')
.height(40)
.onClick(() => {
this.getNetworkInfo();
})
}
.width('90%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(10)
.border({ width: 1, color: Color.Gray })
.margin({ bottom: 30 })
// Network test section
Divider()
.width('90%')
.margin({ bottom: 20 })
Text('Network Connection Test')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// Target host input box
Row() {
Text('Target Host: ')
.fontSize(18)
.fontWeight(FontWeight.Medium)
TextInput({ placeholder: 'Please enter host address', text: this.targetHost })
.fontSize(16)
.width('60%')
.onChange((value: string) => {
this.targetHost = value;
})
}
.width('90%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 20 })
Text(this.networkMessage)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
Button('Execute Network Test')
.fontSize(20)
.width('80%')
.height(50)
.enabled(!this.isNetworkLoading)
.onClick(() => {
this.runNetworkTest();
})
.margin({ bottom: 20 })
if (this.isNetworkLoading) {
Text('Executing Network Test...')
.fontSize(16)
.fontColor(Color.Blue)
.margin({ bottom: 10 })
}
if (this.networkResult) {
Column() {
Text('Network Test Result:')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Scroll() {
Text(this.networkResult)
.fontSize(14)
.fontColor(Color.Black)
.backgroundColor(Color.Gray)
.padding(10)
.borderRadius(5)
.width('100%')
.textAlign(TextAlign.Start)
}
.width('100%')
.height(200)
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.Auto)
}
.width('90%')
}
}
.width('100%')
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Center)
.padding({ top: 10 })
}
.height('100%')
}
aboutToAppear() {
// Get network info when page loads
this.getNetworkInfo();
}
private async getNetworkInfo() {
try {
// Get network connection status
const netHandle = await connection.getDefaultNet();
if (netHandle) {
this.isConnected = true;
// Get network capability information
const netCapabilities = await connection.getNetCapabilities(netHandle);
if (netCapabilities) {
// Determine connection type
if (netCapabilities.bearerTypes.includes(connection.NetBearType.BEARER_WIFI)) {
this.connectionType = 'WiFi';
} else if (netCapabilities.bearerTypes.includes(connection.NetBearType.BEARER_CELLULAR)) {
this.connectionType = 'Mobile Network';
} else if (netCapabilities.bearerTypes.includes(connection.NetBearType.BEARER_ETHERNET)) {
this.connectionType = 'Ethernet';
} else {
this.connectionType = 'Other';
}
}
// Get IP address - using JSON serialization method
const linkProperties = await connection.getConnectionProperties(netHandle);
if (linkProperties) {
// Extract first IPv4 address from serialized info
const serialized: string = JSON.stringify(linkProperties);
const match: RegExpMatchArray | null = serialized.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/);
const ip: string = match ? match[0] : '';
this.currentIpAddress = ip && ip !== '127.0.0.1' ? ip : 'None';
} else {
this.currentIpAddress = 'None';
}
} else {
this.isConnected = false;
this.connectionType = 'Not Connected';
this.currentIpAddress = 'None';
}
} catch (error) {
hilog.error(DOMAIN, 'NetworkInfo', 'Failed to get network info: %{public}s', String(error));
this.isConnected = false;
this.connectionType = 'Get Failed';
this.currentIpAddress = 'Get Failed';
}
}
private async runNetworkTest() {
this.isNetworkLoading = true;
this.networkMessage = 'Network Test in Progress...';
this.networkResult = '';
if (!this.targetHost || this.targetHost.trim() === '') {
this.networkResult = 'Error: Please enter a valid target host address';
this.networkMessage = 'Network Test Failed';
this.isNetworkLoading = false;
return;
}
try {
const startTime = Date.now();
// Use HTTP request to test network connection
const httpRequest = http.createHttp();
const url = this.targetHost.startsWith('http') ? this.targetHost : `https://${this.targetHost}`;
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
connectTimeout: 10000,
readTimeout: 10000,
header: {
'User-Agent': 'OpenHarmony-NetworkTest/1.0'
}
});
const endTime = Date.now();
const responseTime = endTime - startTime;
let resultText = `Network Test Result:\n`;
resultText += `Target Host: ${this.targetHost}\n`;
resultText += `Request URL: ${url}\n`;
resultText += `Response Time: ${responseTime}ms\n`;
resultText += `HTTP Status Code: ${response.responseCode}\n`;
resultText += `Response Header: ${JSON.stringify(response.header, null, 2)}\n`;
if (response.responseCode >= 200 && response.responseCode < 400) {
resultText += `Connection Status: Success\n`;
this.networkMessage = 'Network Test Success';
} else {
resultText += `Connection Status: Failed (HTTP ${response.responseCode})\n`;
this.networkMessage = 'Network Test Failed';
}
// If response body is not too large, show part of the content
if (response.result && typeof response.result === 'string' && response.result.length < 500) {
resultText += `Response Content Preview: ${response.result.substring(0, 200)}...\n`;
}
this.networkResult = resultText;
httpRequest.destroy();
hilog.info(DOMAIN, 'Network_Test', 'Network test completed for %{public}s: %{public}d ms', this.targetHost, responseTime);
} catch (error) {
const errorMessage = String(error);
this.networkResult = `Network Test Failed:\nTarget Host: ${this.targetHost}\nError Message: ${errorMessage}\n\nPossible Reasons:\n1. Network connection unavailable\n2. Target host cannot be accessed\n3. DNS resolution failed\n4. Firewall blocking connection`;
this.networkMessage = 'Network Test Error';
hilog.error(DOMAIN, 'Network_Test', 'Network test error for %{public}s: %{public}s', this.targetHost, errorMessage);
} finally {
this.isNetworkLoading = false;
}
}
}