我正在研究基于 Microchip(Atmel)SAM3X8C 的设计。设计的以太网部分几乎是从 ATSAM3S-EK2-ND 板上复制而来的(我没有,但图纸是制作布局的基础)。我一直与 Microchip 联系,他查看了图纸(和代码)并认为它是正确的。
问题是我无法完成硬件初始化,并且不知道如何继续。
使用的 PHY 是 Davicom DS9161A,它由 ASF 直接支持(选择该部件是因为它与评估板上使用的相同)。与 PHY 的通信正常,我知道这是因为在 ASF 生成的代码中,我正在读取和写入寄存器 - 而我知道其值的寄存器正在读取正确的值(例如,PHYID1 寄存器给出了正确的值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 能够执行自动协商 链路未建立 没有 jabber 扩展寄存器功能
现在,我不知道为什么会出现远程故障情况,也不明白为什么永远无法建立链接。如果我跳过自动协商,并尝试将其强制为 10baseT(全双工或半双工)或 100baseT(全双工或半双工),它仍然具有相同的值。
Microchip 建议我尝试通过回送来隔离问题,但我不确定如何执行此操作。我可以使用网络控制寄存器在 MAC 级别执行此操作,但在完成此操作之后 - 我如何在此级别发送和接收以检查它是否正常工作?我可以使用基本模式控制寄存器在 PHY 级别上执行此操作,但同样,我设置后如何测试?
我正在订购评估板尝试在那里执行此操作 - 以便我可以将结果与我所看到的进行比较,并尝试推断(尽管接口略有不同,因为我使用的是 LQFP 封装,而不是 BGA,但是界面的那部分希望是相同的。
其他可能在堆栈交换中得到回答的机会较小的问题 - 是否有任何地方描述了进出 PHY 的信号应该是什么样的,所以如果是硬件问题,我应该知道该怎么做寻找?
任何对此有任何见解的人,将不胜感激。