Steven Burck
Steven Burck

Reputation: 67

Ethernet PHY difficulties

I'm working on a design based on the Microchip(Atmel)SAM3X8C. The ethernet part of the design is pretty much copied from the ATSAM3S-EK2-ND board (which I don't have, but the drawings were the basis of the layout which was made). I have been in touch with Microchip who looked over the drawings (and the code) and think that it is correct.

The issue is that I am unable to complete hardware initialization, and am at a loss of how to continue.

The PHY being used is the Davicom DS9161A, which is directly supported by the ASF (the part was chosen as it was the same as used on the evaluation board). Communication to the PHY is working, I know this because in the ASF generated code, I am reading and writing registers - and the registers which I know the values of are reading the correct values (for example, the PHYID1 register is giving a correct value of 0x0181).

The issue occurs when trying to bring up a link. If I try to do auto-configuration, it fails with a timeout. This happens in the ASF generated code which tries to do auto-negotiation. I am including the code here so I can make some comments about what I have tried up to this point:

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;
}

The code (as is) fails in the timeout check after a long while. The value in ul_value is always 0x7859, which, as far as I understand, means:

DM9161A is not able to perform in 100BASE-T4 mode DM9161A is able to perform 100BASE-TX in full duplex mode DM9161A is able to perform 100BASE-TX in half duplex mode DM9161A is able to perform 10BASE-T in full duplex mode DM9161A is able to perform 10BASE-T in half duplex mode PHY will accept management frames with preamble suppressed Auto-negotiation process not completed Remote fault condition detected DM9161A is able to perform auto-negotiation Link is not established No jabber Extended register capable

Now, I don't know why there is a remote fault condition, nor do I understand why the link is never established. If I skip the auto-negotiation, and try to force it to 10baseT (full or half duplex) or 100baseT (full or half duplex), it still has the same value.

Microchip suggested that I try to isolate the problem by doing loopback, but I am unsure of how to do this. I can do it on the MAC level using the Network Control Register, but after having done this - how do I send and receive at this level to check if it is working? I can do it on the PHY level using the Basic Mode Control Register, but again, how to test after I have set this?

I am ordering the evaluation board to attempt to do this there - so that I can compare the results with what I am seeing, and try to extrapolate (although the interface is slightly different, as I am using the LQFP package, not the BGA, but that part of the interface is hopefully identical.

Other questions which probably have less of a chance of getting answered on stack exchange - is there anywhere a description of what the signals going into and out of the PHY should look like, so that if it is a hardware issue, I should know what to look for?

Anyone who has any insight into this, any help would be appreciated.

Upvotes: 1

Views: 1010

Answers (2)

shaikh kamal
shaikh kamal

Reputation: 36

The code (as is) fails in the timeout check after a long while. The value in ul_value is always 0x7859, which, as far as I understand, means:

Please read the value of Basic Mode Control Register (BMCR), check 11 bit(IEEE Power Down) value. If its zero thats means PHY register we can access but some operation or link can't be established or auto-negation time out will happen.

Correspondingly check in data sheet how to enable the INT/PWDN in register or any strap configuration, for my case enable the 7th bit CFG3 register. It might resolve the above issue.

Upvotes: 0

Steven Burck
Steven Burck

Reputation: 67

Answer is bad connection of the RJ11 connector to the board, which, once fixed, solved the problem.

Upvotes: 2

Related Questions