我把 gmac 修改成可以在线调整 tx_delay , rx_delay 部份放到这一篇了
你可以测试看看,基本上我认為应该是调整一下,就可以解决你的问题了
我把 gmac 修改成可以在线调整 tx_delay , rx_delay 部份放到这一篇了
你可以测试看看,基本上我认為应该是调整一下,就可以解决你的问题了
天天挖坑,老是有坑在!
MQ-R 的 dts 默认没有把 gmac 使能,故要在 dts 开头处把 gmac 加上
compatible = "allwinner,d1", "arm,sun20iw1p1", "allwinner,sun20iw1p1";
aliases {
dsp0 = &dsp0;
dsp0_gpio_int= &dsp0_gpio_int;
gmac0 = &gmac0;
};
另外 DTS 默认驱动能力只有 10 , 若是非自制在同一片板子,使用开发版自行串接的,驱动能力可能不行! 故可以自上改动一些
// mq-r
gmac_pins_a: gmac@0 {
pins = "PG0", "PG1", "PG2", "PG3",
"PG4", "PG5", "PG6", "PG7",
"PG8", "PG9" , "PG10",
"PG12", "PG13", "PG14", "PG15";
function = "gmac0";
// drive-strength = <10>;
drive-strength = <40>;
};
另外很多文章中介绍使用 iperf3 来测试! 但是运行中有问题
当连接在 百兆
iperf3 -s ok
iperf3-c ok
当连接在 千兆
iperf3 -s ok
iperf3 -c 连 10兆 都达不到
若使用 make menuconfig 中改用 iperf 版本
以上都正常了!
异常
正常
接收可达 400兆
另外 tx_delay , rx_delay 在千兆中调整十分重要! 不能直接使用 dts 中默认配的那一个! 有自已编写了一些测试工具! 若有人有需求可以提供!
d1-h 和 d1s (f133) 架构是一样的,之前调试时也出过类似的问题,你可以参考下面这一篇
另外,你的版子是自已画的,还是用啥开发版吗? 那开发版有试过其他人的固件有一样的问题吗?
若是自已画的 RGMII 上的走线要尽量一样等长,不要过 via ! 并且要注意 gnd 的铺设防止串音!
若是别人的固件可以,你的固件有问题! 那就要查看看 dts 中的 tx_delay , rx_delay 的配置!
这个配合的 phy 芯片、pcb 走线 都会造成异动,不能造抄!
依你的图判断, mcu 读不到你连接的 phy id ,并且收不到 rmii 的 125Mhz 的 clk
所以产生硬件出错!
你可以先查一些查东西!
这儿调完之后,就开始要调 tx-delay 及 rx-dealy ,并不是硬件出错排除后,就可以通了!
还要调 io 时序!
你的版子是购买外面的开发版吗? 还是自已 layout 的呢?
因為 rgmii 上跑的是 125Mhz ,所以若是飞线的 9 成9 是过不了的
你要注意一下,这儿的 spi 速度值并不是可以随便设置的! 因為 cpu 除频后会配不上! 会跳到默认的 10Mhz 的速度。
建议你可以在 .... spi 中,加打印,看看你那值是否可以通过!
/driver/spi/spi-sunxi.c 中
/* set spi clock */
static void spi_set_clk(u32 spi_clk, u32 ahb_clk, struct sunxi_spi *sspi)
{
u32 spi_test = 100000000;
u32 get_spi;
dprintk(DEBUG_INFO, "set spi clock %d, mclk %d\n", spi_clk, ahb_clk);
for(spi_test = 50000000; spi_test >= 20000000; spi_test -= 1000000)
{
clk_set_rate(sspi->mclk, spi_test);
get_spi = clk_get_rate(sspi->mclk);
printk("spi_test %d == get %d \n", spi_test, get_spi);
}
像我以 100Mhz 到 80Mhz , 每 1Mhz 做变化!
[ 1.079831] spi_test 100000000 == get 100000000 ␍␊
[ 1.093426] spi_test 99000000 == get 96000000 ␍␊
[ 1.098527] spi_test 98000000 == get 96000000 ␍␊
[ 1.103587] spi_test 97000000 == get 96000000 ␍␊
[ 1.108714] spi_test 96000000 == get 96000000 ␍␊
[ 1.113807] spi_test 95000000 == get 92307692 ␍␊
[ 1.118905] spi_test 94000000 == get 92307692 ␍␊
[ 1.123996] spi_test 93000000 == get 92307692 ␍␊
[ 1.129127] spi_test 92000000 == get 87771428 ␍␊
[ 1.134193] spi_test 91000000 == get 87771428 ␍␊
[ 1.139293] spi_test 90000000 == get 87771428 ␍␊
[ 1.144406] spi_test 89000000 == get 87771428 ␍␊
[ 1.149506] spi_test 88000000 == get 87771428 ␍␊
[ 1.154601] spi_test 87000000 == get 85714285 ␍␊
[ 1.159739] spi_test 86000000 == get 85714285 ␍␊
[ 1.164835] spi_test 85000000 == get 80000000 ␍␊
[ 1.169939] spi_test 84000000 == get 80000000 ␍␊
[ 1.175074] spi_test 83000000 == get 80000000 ␍␊
[ 1.180142] spi_test 82000000 == get 80000000 ␍␊
[ 1.185243] spi_test 81000000 == get 80000000 ␍␊
[ 1.190346] spi_test 80000000 == get 80000000 ␍␊
就可以知道,有一些值设置是不行的! 要特定值才行!
我把 gmac 修改成可以在线调整 tx_delay , rx_delay 部份放到这一篇了
你可以测试看看,基本上我认為应该是调整一下,就可以解决你的问题了
在修改 tx_delay , rx_delay 需要在dts 中配置,每次都要重新再烧写过! 所以在调试时需要耗费很多气力。只要修改一下原本的驱动,就可以无需另外的工具,就可以进行的调试
驱动位置 lichee/linux-5.4/drivers/net/ethernet/allwinner/sunxi-gmac.c
原代码
static ssize_t mii_write_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct net_device *ndev = NULL;
struct geth_priv *priv = NULL;
int ret = 0;
u16 reg, addr, val;
char *ptr;
ptr = (char *)buf;
if (dev == NULL) {
pr_err("Argment is invalid\n");
return count;
}
ndev = dev_get_drvdata(dev);
if (ndev == NULL) {
pr_err("Net device is null\n");
return count;
}
priv = netdev_priv(ndev);
if (priv == NULL) {
pr_err("geth_priv is null\n");
return count;
}
if (!netif_running(ndev)) {
pr_warn("eth is down!\n");
return count;
}
ret = sunxi_parse_write_str(ptr, &addr, ®, &val);
if (ret)
return ret;
priv->mii_reg.reg = reg;
priv->mii_reg.addr = addr;
priv->mii_reg.value = val;
return count;
}
攸改过后
static ssize_t mii_write_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct net_device *ndev = NULL;
struct geth_priv *priv = NULL;
int ret = 0;
u16 reg, addr, val;
char *ptr;
ptr = (char *)buf;
if (dev == NULL) {
pr_err("Argment is invalid\n");
return count;
}
ndev = dev_get_drvdata(dev);
if (ndev == NULL) {
pr_err("Net device is null\n");
return count;
}
priv = netdev_priv(ndev);
if (priv == NULL) {
pr_err("geth_priv is null\n");
return count;
}
if (!netif_running(ndev)) {
pr_warn("eth is down!\n");
return count;
}
ret = sunxi_parse_write_str(ptr, &addr, ®, &val);
if (ret)
return ret;
if((2 == reg) || (3 == reg))
{
u32 clk_value;
u8 tdelay;
u8 rdelay;
clk_value = readl(priv->base_phy);
tdelay = (clk_value >> 10) & 0x07;
rdelay = (clk_value >> 5) & 0x1f;
printk("gmac delay read tx--> %x , rx--> %x \n", tdelay, rdelay);
if(2 == reg)
{
tdelay = (val & 0x07);
}
else
{
rdelay = (val & 0x1f);
}
printk("gmac delay write tx--> %x , rx--> %x \n", tdelay, rdelay);
clk_value &= ~((0x07 << 10)| (0x1F << 5));
clk_value |= ((tdelay << 10) | (rdelay << 5));
writel(clk_value, priv->base_phy);
}
priv->mii_reg.reg = reg;
priv->mii_reg.addr = addr;
priv->mii_reg.value = val;
return count;
}
使用方式如下:
先使用 ifconfig eth0 192.168.1.100 ,啟动 gmac 驱动
使用下面命令,进行 tx_delay 修改,3 个参数 , 第一个随便设,第二个需设置 2 , 第三个為 tx_delay 设置值,范围 0x0 ~ 0x7
root@TinaLinux:/# echo 0 2 3 > /sys/devices/platform/soc@3000000/4500000.eth/mii_write
[ 66.901376] gmac delay read tx--> 2 , rx--> d
[ 66.911086] gmac delay write tx--> 3 , rx--> d
root@TinaLinux:/# echo 0 2 5 > /sys/devices/platform/soc@3000000/4500000.eth/mii_write
[ 92.944996] gmac delay read tx--> 3 , rx--> d
[ 92.954582] gmac delay write tx--> 5 , rx--> d
root@TinaLinux:/# echo 0 3 a > /sys/devices/platform/soc@3000000/4500000.eth/mi_write
[ 108.317230] gmac delay read tx--> 5 , rx--> d
[ 108.327034] gmac delay write tx--> 5 , rx--> a
root@TinaLinux:/# echo 0 3 1c > /sys/devices/platform/soc@3000000/4500000.eth/mii_write
[ 120.347615] gmac delay read tx--> 5 , rx--> a
[ 120.357371] gmac delay write tx--> 5 , rx--> 1c
root@TinaLinux:/# echo 0 3 1c > /sys/devices/platform/soc@3000000/4500000.eth/mii_write
[ 126.976849] gmac delay read tx--> 5 , rx--> 1c
[ 126.986301] gmac delay write tx--> 5 , rx--> 1c
测试时先使用外机 ping d1s ,调整 rx_delay 值后,使用 ifconfig 查看 rx_byte 及 crc 值,看是否有正常接收,并且无 crc 。 找出某一区间都正常,例如 4 ~ c 都是正常的! 此时将 rx_delay 设置在 8 。
rx_delay 设置后,在用 d1s ping 外机,调整 tx_delay 值,看在什么区间可以正常 ping 不丢包, 一样取中间值
@jxzhb 在 D1-H千兆网络丢包问题 中说:
板子是自己画的,只有一个测试固件没有丢包。我们自己的固件DTS是和测试固件一致的
只要别人的固件没丢包! 那肯定就 3 个地方!
drive-strength / rx_delay / tx_delay 参数配置! 你们有别人的固件原码的 dts 吗? 和你们配置是一样的吗?
若没有可以改一下程序 gamc.c ,在线配置改动一下! 测试 rx_delay , tx_delay 的参数!
先用外机来 ping
然后先调 rx_dealy 0 ~ 31 看看那一些值 crc 不报错! 取中间值
再然后调 tx_dealy 0 ~ 7 , 看看啥值 ping 不丢包,一样取中间值
反正我是这样改的! 用 mq-r 的开发版转到自已的千兆 phy ,是可以正常工作!
d1-h 和 d1s (f133) 架构是一样的,之前调试时也出过类似的问题,你可以参考下面这一篇
另外,你的版子是自已画的,还是用啥开发版吗? 那开发版有试过其他人的固件有一样的问题吗?
若是自已画的 RGMII 上的走线要尽量一样等长,不要过 via ! 并且要注意 gnd 的铺设防止串音!
若是别人的固件可以,你的固件有问题! 那就要查看看 dts 中的 tx_delay , rx_delay 的配置!
这个配合的 phy 芯片、pcb 走线 都会造成异动,不能造抄!
天天挖坑,老是有坑在!
MQ-R 的 dts 默认没有把 gmac 使能,故要在 dts 开头处把 gmac 加上
compatible = "allwinner,d1", "arm,sun20iw1p1", "allwinner,sun20iw1p1";
aliases {
dsp0 = &dsp0;
dsp0_gpio_int= &dsp0_gpio_int;
gmac0 = &gmac0;
};
另外 DTS 默认驱动能力只有 10 , 若是非自制在同一片板子,使用开发版自行串接的,驱动能力可能不行! 故可以自上改动一些
// mq-r
gmac_pins_a: gmac@0 {
pins = "PG0", "PG1", "PG2", "PG3",
"PG4", "PG5", "PG6", "PG7",
"PG8", "PG9" , "PG10",
"PG12", "PG13", "PG14", "PG15";
function = "gmac0";
// drive-strength = <10>;
drive-strength = <40>;
};
另外很多文章中介绍使用 iperf3 来测试! 但是运行中有问题
当连接在 百兆
iperf3 -s ok
iperf3-c ok
当连接在 千兆
iperf3 -s ok
iperf3 -c 连 10兆 都达不到
若使用 make menuconfig 中改用 iperf 版本
以上都正常了!
异常
正常
接收可达 400兆
另外 tx_delay , rx_delay 在千兆中调整十分重要! 不能直接使用 dts 中默认配的那一个! 有自已编写了一些测试工具! 若有人有需求可以提供!
在测试购买的 F133 板子,飞线到自已的板子上时! 一直产生资料报错!
不停的找错时,发现 dts 中有関 drive-strength 的配置值有正相関!
看到 dts 中这值,有 3 种 10 , 20 , 30 。
原本设置 10 时会报错! 改设置成 30 时! 报错大大的减少。
这个没看到有文件说明! 全志的相関文档都说,要看 gpio ,但是 gpio 的 pdf 中,也没有针对这值的说明! 那这个值最大值是多少?
我看 datasheet 中写的是! 默认 io 是 4mA 不是这个对应的数值是多少! 最大是 6mA 。
按很多大老的分享! https://bbs.aw-ol.com/topic/1673/全志芯片tina-linux-修改-uart-引脚-uart端口?lang=zh-CN
按其操作! 结果卡死在这儿
自已一顿操作! 发现一些和一些大老分享不一样的地方
uart3_pins_a: uart3_pins@0 { /* for mq-r uart3 */
pins = "PB6", "PB7";
function = "uart3";
muxsel = <7>;
drive-strength = <10>;
bias-pull-up;
};
uart3_pins_b: uart3_pins@1 { /* For mq-r uart3 */
pins = "PB6", "PB7";
function = "gpio_in";
};
function 很多大老指向 uart0 ,但是这个明明是给 uart3 用的!
再者 muxsel 必需要改成 7 ,这个才是 uart3 功能
/*
&uart0 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart0_pins_a>;
pinctrl-1 = <&uart0_pins_b>;
status = "okay";
};
&uart3 {
compatible = "allwinner,sun20iw1-dsp-uart";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart3_pins_a>;
pinctrl-1 = <&uart3_pins_a>;
status = "disabled";
};
mq-r
*/
&uart0 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart0_pins_a>;
pinctrl-1 = <&uart0_pins_b>;
status = "disabled";
};
&uart3 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&uart3_pins_a>;
pinctrl-1 = <&uart3_pins_b>;
status = "okay";
};
这一句一定要删掉,要不然就开不起来
compatible = "allwinner,sun20iw1-dsp-uart";
目前坑还在接著挖! 有新坑再上来 po 文