以太网PHY困难

时间:2017-10-25 14:07:51

标签: ethernet atmel asf

我正在开发基于Microchip(Atmel)SAM3X8C的设计。设计的以太网部分几乎是从ATSAM3S-EK2-ND板上复制的(我没有,但图纸是制作布局的基础)。我一直与Microchip联系,他们查看了图纸(和代码)并认为它是正确的。

问题在于我无法完成硬件初始化,并且无法继续使用。

正在使用的PHY是Davicom DS9161A,它直接由ASF支持(选择的部分与评估板上使用的相同)。与PHY的通信正在工作,我知道这是因为在ASF生成的代码中,我正在读写寄存器 - 我知道值的寄存器正在读取正确的值(例如,PHYID1寄存器给出了正确的值of 0x0181)。

尝试启动链接时会出现此问题。如果我尝试进行自动配置,则会因超时而失败。这发生在ASF生成的代码中,该代码尝试进行自动协商。我在这里包含了代码,所以我可以就我到目前为止所做的尝试发表一些意见:

uint8_t ethernet_phy_auto_negotiate(Emac *p_emac, uint8_t uc_phy_addr)
{
    uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
    uint32_t ul_value;
    uint32_t ul_phy_anar;
    uint32_t ul_phy_analpar;
    uint32_t ul_retry_count = 0;
    uint8_t uc_fd = 0;
    uint8_t uc_speed = 0;
    uint8_t uc_rc = EMAC_TIMEOUT;

    emac_enable_management(p_emac, true);

    /* Set up control register */
    uc_rc = emac_phy_read(p_emac, uc_phy_addr, MII_BMCR, &ul_value);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    ul_value &= ~MII_AUTONEG; /* Remove auto-negotiation enable */
    ul_value &= ~(MII_LOOPBACK | MII_POWER_DOWN);
    ul_value |= MII_ISOLATE; /* Electrically isolate PHY */
    uc_rc = emac_phy_write(p_emac, uc_phy_addr, MII_BMCR, ul_value);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    /* 
     * Set the Auto_negotiation Advertisement Register.
     * MII advertising for Next page.
     * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
     */
    ul_phy_anar = MII_TX_FDX | MII_TX_HDX | MII_10_FDX | MII_10_HDX | 
            MII_AN_IEEE_802_3;
    uc_rc = emac_phy_write(p_emac, uc_phy_addr, MII_ANAR, ul_phy_anar);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    /* Read & modify control register */
    uc_rc = emac_phy_read(p_emac, uc_phy_addr, MII_BMCR, &ul_value);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    ul_value |= MII_SPEED_SELECT | MII_AUTONEG | MII_DUPLEX_MODE;
    uc_rc = emac_phy_write(p_emac, uc_phy_addr, MII_BMCR, ul_value);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    /* Restart auto negotiation */
    ul_value |= MII_RESTART_AUTONEG;
    ul_value &= ~MII_ISOLATE;
    uc_rc = emac_phy_write(p_emac, uc_phy_addr, MII_BMCR, ul_value);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    /* Check if auto negotiation is completed */
    while (1) {
        uc_rc = emac_phy_read(p_emac, uc_phy_addr, MII_BMSR, &ul_value);
        if (uc_rc != EMAC_OK) {
            emac_enable_management(p_emac, false);
            return uc_rc;
        }
        /* Done successfully */
        if (ul_value & MII_AUTONEG_COMP) {
            break;
        }

        /* Timeout check */
        if (ul_retry_max) {
            if (++ul_retry_count >= ul_retry_max) {
                emac_enable_management(p_emac, false);
                return EMAC_TIMEOUT;
            }
        }
    }

    /* Get the auto negotiate link partner base page */
    uc_rc = emac_phy_read(p_emac, uc_phy_addr, MII_ANLPAR, &ul_phy_analpar);
    if (uc_rc != EMAC_OK) {
        emac_enable_management(p_emac, false);
        return uc_rc;
    }

    /* Set up the EMAC link speed */
    if ((ul_phy_anar & ul_phy_analpar) & MII_TX_FDX) {
        /* Set MII for 100BaseTX and Full Duplex */
        uc_speed = true;
        uc_fd = true;
    } else if ((ul_phy_anar & ul_phy_analpar) & MII_10_FDX) {
        /* Set MII for 10BaseT and Full Duplex */
        uc_speed = false;
        uc_fd = true;
    } else if ((ul_phy_anar & ul_phy_analpar) & MII_TX_HDX) {
        /* Set MII for 100BaseTX and half Duplex */
        uc_speed = true;
        uc_fd = false;
    } else if ((ul_phy_anar & ul_phy_analpar) & MII_10_HDX) {
        /* Set MII for 10BaseT and half Duplex */
        uc_speed = false;
        uc_fd = false;
    }

    emac_set_speed(p_emac, uc_speed);
    emac_enable_full_duplex(p_emac, uc_fd);

    emac_enable_rmii(p_emac, ETH_PHY_MODE);
    emac_enable_transceiver_clock(p_emac, true);

    emac_enable_management(p_emac, false);
    return uc_rc;
}

代码(按原样)在一段时间后超时检查失败。 ul_value中的值始终为0x7859,据我所知,这意味着:

DM9161A无法在100BASE-T4模式下执行 DM9161A能够以全双工模式执行100BASE-TX DM9161A能够以半双工模式执行100BASE-TX DM9161A能够以全双工模式执行10BASE-T DM9161A能够以半双工模式执行10BASE-T PHY将接受具有前导码抑制的管理帧 自动协商过程未完成 检测到远程故障情况 DM9161A能够执行自动协商 链接尚未建立 没有唠叨 具有扩展寄存器

现在,我不知道为什么会出现远程故障情况,也不明白为什么链接永远不会建立。如果我跳过自动协商,并尝试强制它为10baseT(全双工或半双工)或100baseT(全双工或半双工),它仍具有相同的值。

Microchip建议我尝试通过环回来解决问题,但我不确定如何执行此操作。我可以使用网络控制寄存器在MAC级别上执行此操作,但在完成此操作后 - 如何在此级别发送和接收以检查它是否正常工作?我可以使用基本模式控制寄存器在PHY级别上执行此操作,但同样,在设置此项后如何测试?

我正在命令评估板尝试在那里进行 - 我可以将结果与我看到的结果进行比较,并尝试进行推断(尽管界面略有不同,因为我使用的是LQFP封装,而不是BGA,但界面的那部分希望是相同的。

其他可能没有机会在堆栈交换中得到回答的问题 - 在任何地方都可以描述进出PHY的信号应该是什么样的,所以如果它是硬件问题,我应该知道该找什么?

任何对此有任何见解的人都会感激不尽。

2 个答案:

答案 0 :(得分:1)

答案是RJ11连接器与电路板连接不良,一旦修复,就解决了问题。

答案 1 :(得分:0)

代码(按原样)在一段时间后超时检查失败。 ul_value中的值始终为0x7859,据我所知,这意味着:

请读取基本模式控制寄存器(BMCR)的值,检查11位(IEEE断电)值。如果它的零意味着PHY寄存器我们可以访问但是某些操作或链接无法建立或自动否定超时将发生。

相应地检查数据手册中如何启用寄存器中的INT / PWDN或任何带配置,对于我的情况,启用第7位CFG3寄存器。 它可能会解决上述问题。