2416开发板上网卡芯片lan9220的时序配置问题
最近在学习某品牌的2416(不好评论)开发板,其他都还好,就这个网卡把我折磨得够呛。lan9220这款网卡芯片功能极其强大,能耗控制,远程唤醒,高度集成PHY与MAC, 10Mbps/100Mbps等,但是建议各位在非极端情况下不要采用此款芯片,至少在与2416搭配时不要采用此芯片。
发现的硬伤(2416与lan9220搭配时),未在其他开发板上测试,仅供参考:
现象1:lan9220触发的中断信号使用2416的GPG7,外部中断15,当我们采用下降沿进行触发时,会出现抖动,造成触发2次中断,2次中断还特别怪异,第一次外部中断状态置1,内部中断PND与SRC都置1,当我们清除后,第二次进入中断,只有内部中断PND与SRC置1,外部中断状态全0.(这个与朋友讨论结论:有可能是2416的电源没有保护好,不管了,反正我们搞软件的)。(注:此时我们仅开通了内部中断5管理的外部中断15,其他的8到14全部关闭状态中。
现象2:当使能发送时(TX_EN),如果再次使能接受使能(RX_EN),TX_EN的使能会被错误的关闭。
现象3:HBI层的寄存器能正常访问,MAC层的寄存器组,对MAC_CSR_CMD的写必须使用busy mode(使用说明没提到),PHY层的寄存器组反应速度比较慢,这也是我今天要说明的东西。
首先在lan9220的手册上提到的一些时序问题,我们就不再这里讨论了,我们来说说他漏掉的一些时序问题。
因为lan9220的mac层与phy层的寄存器是不能直接被访问的,都是逐级调用寄存器来进行来访问的,但我对mac进行按照说明书上的步骤进行访问时出现一个现象是:
本来phy_id1的默认值是7 id2默认值是c0c3的,但是他们都被错误的读取了。我的程序如下:
static unsigned long HBI_read(unsigned char offset)
{
return __REG(LAN9220_BASEADDR | (offset & 0xFF));
}
static void HBI_write(unsigned char offset, unsigned long value)
{
__REG(LAN9220_BASEADDR | (offset & 0xFF)) = (RAW_U32)value;
}
static unsigned long mac_read(unsigned int index)
{
unsigned long reg = 0;
while (HBI_read(MAC_CSR_CMD) & (0x1 << 31)) {
delay(1);
}
HBI_write(MAC_CSR_CMD, (0x1 << 31) | (0x1 << 30) | (index & 0xFF));
reg = HBI_read(MAC_CSR_DATA);
while (HBI_read(MAC_CSR_CMD) & (0x1 << 31)) {
delay(1);
}
return reg;
}
static void mac_write(unsigned int index, unsigned long value)
{
while (HBI_read(MAC_CSR_CMD) & (0x1 << 31)) {
delay(1);
}
HBI_write(MAC_CSR_DATA, value);
HBI_write(MAC_CSR_CMD, (0x1 << 31) | (index & 0xFF));
while (HBI_read(MAC_CSR_CMD) & (0x1 << 31)) {
delay(1);
}
}
static unsigned long phy_read(unsigned int index)
{
unsigned short reg = 0;
while (mac_read(MII_ACC) & 0x1);
mac_write(MII_ACC, (0x1) | (index << 6) | (0x01 << 11));
reg = mac_read(MII_DATA) & 0xFFFF;
while (mac_read(MII_ACC) & 0x1);
return reg;
}
static void phy_write(unsigned int index, unsigned short value)
{
while (mac_read(MII_ACC) & 0x1);
mac_write(MII_DATA, (unsigned long)(value & 0xFFFF));
mac_write(MII_ACC, (0x1) | (0x1 << 1) | (index << 6) | (0x01 << 11));
while (mac_read(MII_ACC) & 0x1);
}
static void delay(int cnt)
{
while (cnt--)
{
HBI_read(BYTE_TEST);
}
}
但我对mac_read/mac_write进行debug时,添加打印信息,缺又偶然的得到了正确的反馈信息,说明对phy层寄存器的操作需要添加一定延时,来满足寄存器相应。大概流程如下:
DATA---》delay--->cmd--->wait for complete
写操作
Cmd--->delay----->data---->delay---->wait for complete
读操作
注意,在这2组操作之间也需要一定的延时来插入。
大概就这样吧。