前言
STM32MP257系列是一款双核A35的MPU,同时带有一个千兆switch功能的芯片,switch分别支持RMII/RGMII接口的PHY,STM32官方已经提供了STM32MP257-EV参考设计板,支持是RGMII,同时wiki也有关于switch配置RGMII PHY设备参考。这篇文章主要关于switch接RMII百兆PHY的硬件设计,设备配置和TSN switch软件功能使能。
1. 概括
STM32MP257系列的MPU都带有两个独立的网口ETH1和ETH2,同时带有switch功能,ETH1既可以配置为普通网口,也可以使能switch功能,当使能switch功能后ETH3可以接PHY,switch及可以支持RMII接口的百兆PHY,也可以支持RGMII接口的千兆PHY如下图框:

STM32MP257系列的硬件的switch设计和不带switch的硬件设计大致相同,可以参考硬件设计文档AN5489。ETH1 Switch硬件支持的功能有两部分组成,分别是DeIP标准的802.1功能和ACM模块,如下图:

因此软件kernel驱动大概有三部分:
STM32 deip glue:用来配置rcc时钟;
Switch driver(edge-lkm):用来配置switch DeIP和TSN应用支持;
ACM driver:控制ACM寄存器;
Switch使能后默认的网络配置如下:

end0,ETH2口,是独立的GMAC接口。
end1,ETH1口,既可以做独立的GMAC接口,也可以使能switch。
Switch使能后如下描述几个口的含义:
Sw0p1是对内的GMAC接口,不需要配置IP;
Sw0p2和sw0p3是对外的GMAC接口,分别接ETH3和ETH1口,不需要分配IP;
Sw0ep是终端接口,也是MP2内外通讯的端口,IP要配置到这个口。
2. Developer开发包使能RMII Switch
Developer使能RMII Switch的步骤:
2.1 kernel的配置,如上面图示,switch框架需要使能bridge,所以需要使能如下的配置:
CONFIG_BRIDGE=m CONFIG_BRIDGE_NETFILTER=m CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_VLAN_8021Q=m
2.2 switch是千兆以太网接口,需要提供125Mhz内部时钟,所以需要修改OPTEE时钟如下:
&rcc
{
<...>
st,flexgen = <
<...>
FLEXGEN_CFG(54, XBAR_SRC_PLL6, 0, 3) /* 125 Mhz */
<...>
>;
<...>
}2.3 kernel设备树配置,配置ETH1内部GMAC口和使能switch,如下:
ð1
{
status = "okay";
pinctrl-0 = <ð1_mdio_pins_a>;
pinctrl-names = "default";
phy-mode="rgmii";
phy-handle=<&phy1_eth1>;
st,ext-phyclk;
fixed_link: fixed-link
{
speed=<1000>;
full-duplex;
};
mdio1{
#address-cells=<1>;
#size-cells=<0>;
compatible="snps,dwmac-mdio";
phy1_eth1: ethernet-phy@1 {
compatible="ethernet-phy-id001c.c816";
reset-gpios= <&gpioj 9 GPIO_ACTIVE_LOW>;
max-speed = <100>;
reset-assert-us = <10000>;
reset-deassert-us = <80000>;
reg = <1>;
};
phy2_eth1:ethernet-phy@2 {
compatible = "ethernet-phy-id001c.c816",
"ethernet-phy-ieee802.3-c22";
max-speed = <100>;
reg = <2>;
};
};
};
&switch0 {
status = "okay";
pinctrl-0 = <ð1_rmii_pins_a>;
pinctrl-names = "default";
phy-mode = "rmii";
st,ethsw-internal-125;
};2.4 编译以太网switch驱动模块
> *需要先source MP2开发的SDK* > > PC > git clone https://github.com/STMicroelectronics/tttech-tsn-swchcontent.git -b 1.6.8 > PC > cd st,stm32-deip > PC > INSTALL_MOD_PATH=./install_artifact KDIR=/build platform=st sched=fsc sid=sid make > PC > INSTALL_MOD_PATH=./install_artifact KDIR=/build platform=st sched=fsc sid=sid make modules_install > > PC > cd ../tsn_sw_base.edge-lkm > PC > INSTALL_MOD_PATH=./install_artifact KDIR=/build platform=st sched=fsc sid=sid make > PC > INSTALL_MOD_PATH=./install_artifact KDIR=/build platform=st sched=fsc sid=sid make modules > PC > INSTALL_MOD_PATH=./install_artifact KDIR=/build platform=st sched=fsc sid=sid make modules_install
2.5 运行脚本
./switch_init.sh: modprobe 8021q modprobe bridge modprobe sch_prio modprobe sch_mqprio modprobe stm32_deip modprobe edgx_pfm_lkm netif="eth0:0" //这个是以太网ETH1的网络名,如果不一样,需要修改
2.6 ttt-ip-init.sh start:这个脚本可以通过distribution编译带有个TSN-SWITH的文件系统copy出来。
#!/bin/sh
REF_ETH_INTERFACE=eth0
IP_REF_NAME=42080000.bus/42080000.bus:ttt-sw@4c000000/4c000000.deip-sw
# read mac address
get_mac() {
read MAC </sys/class/net/$REF_ETH_INTERFACE/address
echo "[INFO]: Mac Address of $REF_ETH_INTERFACE: $MAC"
}
get_soc_path() {
devicetree_path=$(ls -1 -d /sys/devices/platform/* | grep "/soc" | head -n 1)
if [ -d "$devicetree_path" ];
then
SOC_PATH=$devicetree_path
else
echo "[ERROR]: /sys/devices/platform/soc* is not available"
echo ""
exit 1
fi
}
wait_sysfs() {
path=$1
for i in $(seq 0 5)
do
if [ ! -e "$path" ]; then
break;
else
sleep 0.5s
fi
done
}
st_configure() {
get_soc_path
wait_sysfs $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus
if [ -e $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus ]; then
echo -n stmmac-1:01 > $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus
echo -n stmmac-1:02 > $SOC_PATH/$IP_REF_NAME/net/sw0p2/phy/mdiobus
else
echo "[ERROR]: $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus not available"
echo ""
exit 1
fi
echo 170 > /sys/class/net/sw0p2/phy/delay1000tx_min
echo 200 > /sys/class/net/sw0p2/phy/delay1000tx_max
echo 170 > /sys/class/net/sw0p3/phy/delay1000tx_min
echo 200 > /sys/class/net/sw0p3/phy/delay1000tx_max
echo 520 > /sys/class/net/sw0p2/phy/delay1000rx_min
echo 570 > /sys/class/net/sw0p2/phy/delay1000rx_max
echo 520 > /sys/class/net/sw0p3/phy/delay1000rx_min
echo 570 > /sys/class/net/sw0p3/phy/delay1000rx_max }
# Set the interfaces up like in the interfaces files
# Usage: set_interfaces_up
set_interfaces_up()
{
get_mac
ip link set dev sw0ep address $MAC
ip link set dev sw0ep up
# ask to network to put an ip address on this interface
# udhcpc -i sw0ep > /dev/null 2>&1 &
ip addr add 192.168.0.10 dev sw0ep
ip route add 192.168.0.0/24 dev sw0ep
sleep 1
ip link add name br0 type bridge
ip link set dev br0 up
ip link set dev sw0p1 master br0 up
ip link set dev sw0p2 master br0 up
ip link set dev sw0p3 master br0 up
ip link set dev sw0ep up
echo "[INFO]: ST interfaces are up"
}
# Set the interfaces down like in the interfaces files
# Usage: set_interfaces_down
set_interfaces_down()
{
ip link set dev br0 down
ip link delete dev br0
ip link set dev sw0ep down
}
# Start the deamons as they would do at start
# Usage: start_daemons
start_daemons()
{
# stop NTP service
systemctl stop systemd-timesyncd
systemctl stop ntpd
ip link set br0 type bridge stp_state 1
mstpctl addbridge br0
mstpctl setforcevers br0 mstp
mstpctl setvid2fid br0 0:1
systemctl start lldpd &
systemctl start deptp &
#systemctl start snmpd &
/usr/share/netopeer2-server/netopeer2-server-service start &
}
# Stop the daemons
# Usage:
stop_daemons stop_daemons()
{
mstpctl delbridge br0
#systemctl stop snmpd &
systemctl stop lldpd &
systemctl stop deptp &
/usr/share/netopeer2-server/netopeer2-server-service stop
}
start()
{
echo "[INFO]: ST configuration of IP"
st_configure
echo "[INFO]: ST set brigde interface"
set_interfaces_up
# echo "[INFO]: start service"
# start_daemons
}
stop() {
# stop_daemons
set_interfaces_down
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
restore)
/usr/share/netopeer2-server/netopeer2-server-service restore
;;
esac
exit 0其中st_configure这个函数里面的stmmac-1根据硬件设计的PHY地址来修改。
echo -n stmmac-1:01 > $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus echo -n stmmac-1:02 > $SOC_PATH/$IP_REF_NAME/net/sw0p2/phy/mdiobus
3. 基于distribution开发包使能RMII Switch
具体步骤:
3.1 编译带有TSN Switch功能的distribution package,具体可以参考这个wiki。bitbake-layers add-layer../layers/meta-st/meta-st-stm32mp-tsn-swch 主要是通过这个指令把tsn-switch的layer添加到yocto的待编译的工程layer中。
3.2 switch是千兆以太网接口,需要提供125Mhz内部时钟,所以需要修改OPTEE时钟如下:
&rcc {
<...>
st,flexgen = <
<...>
FLEXGEN_CFG(54, XBAR_SRC_PLL6, 0, 3) /* 125 Mhz */
<...>
>;
<...>
}3.3 kernel设备树配置,配置ETH1内部GMAC口和使能switch,如下:
ð1 {
status = "okay";
pinctrl-0 = <ð1_mdio_pins_a>;
pinctrl-names = "default";
phy-mode = "rgmii";
phy-handle = <&phy1_eth1>;
st,ext-phyclk;
fixed_link: fixed-link {
speed = <1000>;
full-duplex;
};
mdio1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy1_eth1: ethernet-phy@1 {
compatible = "ethernet-phy-id001c.c816";
reset-gpios = <&gpioj 9 GPIO_ACTIVE_LOW>;
max-speed = <100>;
reset-assert-us = <10000>;
reset-deassert-us = <80000>;
reg = <1>;
};
phy2_eth1: ethernet-phy@2 {
compatible = "ethernet-phy-id001c.c816",
"ethernet-phy-ieee802.3-c22";
max-speed = <100>;
reg = <2>;
};
};
};
&switch0 {
status = "okay";
pinctrl-0 = <ð1_rmii_pins_a>;pinctrl-names = "default";
phy-mode = "rmii";
st,ethsw-internal-125;
};
&switch0 {
status = "okay";
pinctrl-0 = <ð1_rmii_pins_a>;
pinctrl-names = "default";
phy-mode = "rmii";
st,ethsw-internal-125;
};3.4 修改启动脚本(需要注意默认的eth0,eth1已经被重新命名为end0,end1,脚本都是按这个名字修改的),修改文件系统中的/usr/sbin/ttt-ip-init-systemd.sh,如下:
REF_ETH_INTERFACE=eth0
……
st_configure() {
get_soc_path
wait_sysfs $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus
if [ -e $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus ];
then
echo -n stmmac-1:01 >
$SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus /*这个 01 是 RMII 接口 PHY 的物理地址*/
#
#echo
-n stmmac-1:05 > $SOC_PATH/$IP_REF_NAME/net/sw0p2/phy/mdiobus /*因为 MP23x 只设计了两个 口,如果这个口没有引出来,可以注释掉*/
else
echo "[ERROR]: $SOC_PATH/$IP_REF_NAME/net/sw0p3/phy/mdiobus not available"
echo ""
exit 1
fi
};4. 常见问题和注意事情
4.1 因为Switch千兆的RGMII,如果外部接的是RMII百兆的PHY,收发数据的时候内部switch还是按照千兆的网络来收发,所以使用iperf3来测试的时候需要指定带宽参数-b 100M。也可以使用tc指令来系统设置:
tc qdisc replace dev sw0ep root handle 1: htb default 1 r2q 1 tc class replace dev sw0ep parent 1: classid 1:1 htb rate 95Mbit
4.2 如何客人使用的是ST提供的文件系统,有可能自己重新配置了以太网的名字,因此需要修改以下几个脚本的默认名字:
/usr/sbin/ttt-ip-init-systemd.sh //switch驱动使能的以太网名字 /etc/modprobe.d/edgx_sw_core.conf //驱动加载的以太网名字 /usr/lib/systemd/network/80-wired.network //网络ip配置的以太网名字
来源:STM32
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。