SSD_Ethernet
使用参考


1. ETHERNET使用参考


1.1. 以太网架构介绍

从硬件的角度看,以太网接口电路主要由MAC(Media Access Control)控制器和物理层接口PHY(Physical Layer,PHY)两大部分构成。Sigmastar平台内置MAC控制器与内置PHY;同时也支持RMII总线协议,可接外置switch或者PHY芯片。图示如下:


1.2. RMII接口介绍

RMII接口包括一个数据接口,以及一个MAC和PHY之间的管理接口。MDIO管理接口包括两根信号线(MDC与MDIO),通过这个接口MAC可以读取PHY或者Switch芯片寄存器实现传输信息与状态控制。


1.3. uboot下使用RMII

SSD2XX平台举例

1.3.1. uboot下打开RMII支持

menuconfig中使能emac,关闭内置phy并打开rmii接口,如下:


1.3.2. 使用MDIO初始化PHY或者Switch

uboot下提供mdio读写操作函数,见文件:boot/drivers/mstar/emac/pioneer3/mhal_emac.c

MDIO读:

void MHal_EMAC_read_phy(unsigned char phy_addr, unsigned char address,u32
*value)

MDIO写:

void MHal_EMAC_write_phy (unsigned char phy_addr, unsigned char address, u32
value)

参考boot/drivers/mstar/emac/mdrv_emac.c文件中的ip101a_g_config_init函数,使用mdio read/write访问寄存器初始化外部PHY或者Switch芯片。

需要注意的是read操作时,针对主控这边MDC时钟在TA信号后会变成下降沿采样;write操作会一直保持上升沿采样。要确定MDIO是否读写正确可使用逻辑分析仪捕捉MDIO与MDC信号波形。


1.3.3. Uboot下测试MDIO

Uboot下也提供了mdio读写命令,需要先输入estart使能网卡,具体使用方法如下:

mdio读寄存器1如:

SigmaStar # phy_r 1

phy read address[1] value is 78ed

mdio写寄存器0如:

SigmaStar # phy_w 0 1234

phy write address[0] value is 1234

1.4. kernel下使用RMII

SSD2XX举例

1.4.1. kernel中打开网络支持

menuconfig中打开如下选项:


1.4.2. 配置RMII管脚PINMUX

打开kernel/arch/arm/boot/dts/pioneer3-ssc020a-s01a-demo-camera-padmux.dtsi文件,padmux栏位增加如下内容:

{
    soc {
        padmux {
        compatible = "sstar-padmux";
        schematic =

        //for eth0 rmii
        <PAD_GPIO0      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_MDIO>,
        <PAD_GPIO1      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_MDC>,
        <PAD_GPIO2      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_COL>,
        <PAD_GPIO3      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_RXD0>,
        <PAD_GPIO4      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_RXD1>,
        <PAD_GPIO5      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_TX_CLK>,
        <PAD_GPIO6      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_TXD0>,
        <PAD_GPIO7      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_TXD1>,
        <PAD_GPIO8      PINMUX_FOR_ETH0_MODE_11       MDRV_PUSE_ETH_TX_EN>,

        status = "ok";
        };
    };
};

1.4.3. 修改设备树使能RMII

打开kernel/arch/arm/boot/dts/pioneer3-ssc020a-s01a-demo-camera.dts文件,修改如下内容,配置phy-mode为rmii接口:

#if 0
emac0: emac0 {
    compatible = "sstar-emac";
    reg = <0x1F2A2000 0x800>, <0x1F343C00 0x600>, <0x1F006200 0x600>;
    pad = <0x1F2079B8 0x000F 0x0000>;  //for internal phy
    status = "ok";
    phy-handle = <&phy0>;
    mdio-bus {
        phy0: ethernet-phy@0 {
            phy-mode = "mii";
        };
    };
};
#endif

#if 1
//for emac0 rmii
emac0: emac0 {
    compatible = "sstar-emac";
    reg = <0x1F2A2000 0x800>, <0x1F343C00 0x600>, <0x00000000 0x600>;
    pad = <0x1F2079B8 0x000F 0x000B>;  //for external phy
    status = "ok";
    phy-handle = <&phy0>;
    mdio-bus {
        phy0: ethernet-phy@0 {
            phy-mode = "rmii";
        };
    };
};
#endif

1.4.4. 通过MDIO接口初始化PHY或者Switch

Kernel下同样支持mdio读写操作,如下:

MDIO读函数:MDev_EMAC_mii_read

MDIO写函数:MDev_EMAC_mii_write

MII/RMII初始化函数:MDev_EMAC_mii_init

具体代码见kernel/drivers/sstar/emac/mdrv_emac.c文件。用户初始化PHY或者Switch芯片的函数可添加在MDev_EMAC_mii_init函数之后。

static int MDev_EMAC_mii_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
{
    struct emac_handle *hemac = (struct emac_handle *) bus->priv;
    int ret;

    ret = MHal_EMAC_write_phy(hemac->hal, phy_addr, phy_reg, (u32)val);
    return ret;
}

static int MDev_EMAC_mii_read(struct mii_bus *bus, int phy_addr, int phy_reg)
{
    u32 val;
    struct emac_handle *hemac = (struct emac_handle *) bus->priv;
    int ret;

    ret = MHal_EMAC_read_phy(hemac->hal, phy_addr, phy_reg, &val);
    return (int)val;
}

static int MDev_EMAC_mii_init(struct net_device* emac_dev)
{
    struct emac_handle *hemac = (struct emac_handle *) netdev_priv(emac_dev);
    struct device_node *mii_np = NULL;
    int ret = 0;

    ...

    hemac->mii_bus->name = "mdio";
    hemac->mii_bus->read = MDev_EMAC_mii_read;
    hemac->mii_bus->write = MDev_EMAC_mii_write;
    hemac->mii_bus->priv = hemac;
    hemac->mii_bus->parent = hemac->dev;

    ...

    return ret;
}

1.4.5. Kernel下测试MDIO

Kernel起来后通过echo命令操作文件,底层驱动中实现mdio读写寄存器,命令如下:

MDIO读:

echo phy_r phyAddress > phyStatusWR

MDIO写:

echo phy_w phyAddress phyValue > phyStatusWR

示例,读取寄存器1的值;向寄存器0写入0x1234,如下:

# echo phy_r 1 > /sys/devices/virtual/mstar/emac0/phyStatusWR
# echo phy_w 0 1234 > /sys/devices/virtual/mstar/emac0/phyStatusWR

2. ETHERNET常用配置说明


2.1. uboot与kernel下配置IP地址

uboot下使用如下命令设置板端IP与电脑端IP,并使用ping命令测试网络是否连通:

SigmaStar # setenv ipaddr 192.168.50.123

SigmaStar # setenv serverip 192.168.50.249

SigmaStar # ping 192.168.50.249

Using sstar_emac device

host 192.168.50.249 is alive

kernel下使用ifconfig命令配置IP相关属性:

# ifconfig eth0 up
# ifconfig eth0 hw ether 00:70:27:00:00:03
# ifconfig eth0 192.168.50.123 netmask 255.255.255.0
# route add default gw 192.168.50.1

2.2. 使用DHCP自动获取IP

脚本文件位于工程目录project/image/etc/init.d/udhcpc.script,打包image时会拷贝到板端,kernel起来后板端运行udhcpc命令,可自动获取ip,示例如下:

# udhcpc -i eth0 -s /etc/init.d/udhcpc.script
udhcpc (v1.20.2) started
Setting IP address 0.0.0.0 on eth0
Sending discover...
Sending discover...
Sending select for 192.168.50.243...
Lease of 192.168.50.243 obtained, lease time 86400
Setting IP address 192.168.50.243 on eth0
Deleting routers
route: SIOCDELRT: No such process
Adding router 192.168.50.1
Recreating /appconfigs/resolv.conf
Adding DNS server 192.168.50.1

2.3. DNS服务使用介绍

2.3.1. 准备DNS依赖库

打开DNS服务需要依赖相关的库文件,可以从toolchain中拷贝到板端,使用export命令导出动态库。

# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib/libdns

示例,如果使用的是9.1.0的toolchain,则相关的库文件在如下目录:

/tools/toolchain/gcc-sigmastar-9.1.0-2020.07-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/

libnsl-2.30.so
libnsl.so.1
libnss_compat-2.30.so
libnss_compat.so.2
libnss_db-2.30.so
libnss_db.so.2
libnss_dns-2.30.so
libnss_dns.so.2
libnss_files-2.30.so
libnss_files.so.2
libnss_hesiod-2.30.so
libnss_hesiod.so.2
libresolv-2.30.so
libresolv.so.2

2.3.2. 配置DNS服务器

在板端创建/etc/resolv.conf配置文件,并写入对应的dns server ip,如:

# echo "nameserver 8.8.8.8" >> /etc/resolv.conf

2.3.3. 测试DNS

使用ping命令测试dns解析域名,如:

# ping www.baidu.com
PING www.baidu.com (163.177.151.109): 56 data bytes
64 bytes from 163.177.151.109: seq=0 ttl=55 time=7.640 ms
64 bytes from 163.177.151.109: seq=1 ttl=55 time=8.002 ms
64 bytes from 163.177.151.109: seq=2 ttl=55 time=7.443 ms
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 7.443/7.695/8.002 ms

3. ETHERNET带宽测试说明


3.1. 使用iperf测试网络性能

3.1.1. 下载iperf源码

linux端下载地址:

https://iperf.fr/download/source/iperf-2.0.9-source.tar.gz

PC端下载地址:

https://iperf.fr/iperf-download.php#windows

注意:linux端与PC端的iperf版本保持一致

3.1.2. 编译iperf

配置交叉编译器:

./configure --help
./configure --prefix=$(pwd)/host --host=arm-linux-gnueabihf CXX=arm-linux-gnueabihf-g++ CC=arm-linux-gnueabihf-gcc

编译并安装,完成后会在当前目录host/bin下生成可执行档iperf,拷贝到板端:

make clean
make -j4
make install

3.1.3. 测试网络

帮助命令:

# ./iperf –h

-f [k|m|K|M] 分别表示以Kbits, Mbits, KBytes, MBytes显示报告, 默认以Mbits为单位
-i sec 以秒为单位显示报告间隔, eg: iperf -c 222.35.11.23 -i 2
-l 缓冲区大小, 默认是8KB, eg: iperf -c 222.35.11.23 -l 16 -m 显示tcp最大mtu值
-o 将报告和错误信息输出到文件, eg: iperf -c 222.35.11.23 -o /mnt/iperflog.txt
-p 指定服务器端使用的端口或客户端所连接的端口
-u 使用udp协议
-w 指定TCP窗口大小, 默认是8KB
-M 设定TCP数据包的最大mtu值
client端专用参数 
-d 同时进行双向传输测试 
-n 指定传输的字节数, eg: iperf -c 222.35.11.23 -n 100000
-r 单独进行双向传输测试 
-t 测试时间,默认10秒, eg: iperf -c 222.35.11.23 -t 5
-F 指定需要传输的文件
-T 指定ttl值

3.1.4. TCP吞吐测试

PC端作为server,板端作为client。Windows中打开cmd命令行,输入iperf -s以server模式运行iperf,如下图所示:

Linux板端以client模式运行iperf,测试10秒,如下:

# ./iperf -c 192.168.50.249 -i 1 -t 10
------------------------------------------------------------
Client connecting to 192.168.50.249, TCP port 5001
TCP window size:  128 KByte (default)
------------------------------------------------------------
[  3] local 192.168.50.243 port 49902 connected with 192.168.50.249 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec  11.1 MBytes  93.3 Mbits/sec
[  3]  1.0- 2.0 sec  11.2 MBytes  94.4 Mbits/sec
[  3]  2.0- 3.0 sec  11.0 MBytes  92.3 Mbits/sec
[  3]  3.0- 4.0 sec  11.2 MBytes  94.4 Mbits/sec
[  3]  4.0- 5.0 sec  11.2 MBytes  94.4 Mbits/sec

3.1.5. UDP丢包测试

PC端作为server,板端作为client。Windows中打开cmd命令行,输入iperf -s -u以server模式运行iperf,如下图所示:

Linux板端以client模式运行iperf,测试10秒,如下:

# ./iperf -c 192.168.50.249 -i 1 -t 10 -u
------------------------------------------------------------
Client connecting to 192.168.50.249, UDP port 5001
Sending 1470 byte datagrams, IPG target: 11215.21 us (kalman adjust)
UDP buffer size:  512 KByte (default)
------------------------------------------------------------
[  3] local 192.168.50.243 port 57894 connected with 192.168.50.249 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0- 1.0 sec   131 KBytes  1.07 Mbits/sec
[  3]  1.0- 2.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  2.0- 3.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  3.0- 4.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  4.0- 5.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  5.0- 6.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  6.0- 7.0 sec   129 KBytes  1.06 Mbits/sec
[  3]  7.0- 8.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  8.0- 9.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  9.0-10.0 sec   128 KBytes  1.05 Mbits/sec
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec
[  3] Sent 893 datagrams
[  3] Server Report:
[  3]  0.0-10.0 sec  1.25 MBytes  1.05 Mbits/sec   0.417 ms    0/  893 (0%)

4. 典型FAQ举例


Q1:如何添加ephy的网口驱动能力?

[SSD20X][SSD212][SSD22X]适用

riu_r 0x31 0x2E

riu_w 0x31 0x2E 0x7001 //将bit0 set 1

echo swing_100 2 > /sys/devices/virtual/mstar/emac0/turndrv //增强网口驱动能力

riu_r 0x33 0x42 //查看当前网络驱动幅值

Q2:如果有一些超长网线(>200m)的场景怎么办?

[SSD20X][SSD212][SSD22X]适用

传输距离超过100m属于超规格,无法保证可靠性,但是可以尝试将速度限定到10M。

riu_w 0x31 0x04 0x61

riu_w 0x31 0x00 0x1200

echo max > /sys/class/mstar/emac0/turndrv