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的使能会被错误的关闭。

现象3HBI层的寄存器能正常访问,MAC层的寄存器组,对MAC_CSR_CMD的写必须使用busy mode(使用说明没提到),PHY层的寄存器组反应速度比较慢,这也是我今天要说明的东西。

首先在lan9220的手册上提到的一些时序问题,我们就不再这里讨论了,我们来说说他漏掉的一些时序问题。

因为lan9220mac层与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组操作之间也需要一定的延时来插入。

大概就这样吧。