|
这两天调试了一下STM32+ENC28J60环境下的LWIP
软件包是RTT论坛下的版本为RT-Thread-0.3.2
开始时都还好,连续PING 24小时都没有故障,
用NETIO测试了下网络速度,也能正常完成,
当我开了两个CMD窗口同时做这两个测试时,问题来了,ENC28J60不响应了,PING一直TIMEOUT,NETIO也死掉了,
但RTT仍在工作中
我在finsh察看ENC28J60的寄存器时发现ENC28J60的发送错误中断标志位置位了
finsh>>enc28j60()
-- enc28j60 registers:
HwRevID: 0x06
Cntrl: ECON1 ECON2 ESTAT EIR EIE
0x0c 0x80 0x03 0x00 0xc8
MAC : MACON1 MACON3 MACON4
0x0d 0x33 0x40
Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL
0x0000 0x19fe 0x17e2 0x17e2 0xa1 0x00 0x05ee
Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP
0x19ff 0x1e36 0x0f 0x3f 0x10
',', 44, 0x0000002c
finsh>>
查了下论坛,好像一直有人在再说STM32+ENC28J60老有不稳定的现象
ffxz有提说是ENC28J60的驱动的问题,就这情况看了驱动文件
rt_err_t enc28j60_tx( rt_device_t dev, struct pbuf* p)
{
struct pbuf* q;
rt_uint32_t len;
rt_uint8_t* ptr;
rt_uint32_t level;
。。。
// send the contents of the transmit buffer onto the network
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
// Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
if( (spi_read(EIR) & EIR_TXERIF) )
{
spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); <----这里看起来作了错误处理,但好像没有用
}
/* enable enc28j60 interrupt */
enc28j60_interrupt_enable(level);
rt_sem_release(&lock_sem);
return RT_EOK;
}
于是翻了下中断服务
void enc28j60_isr()
{
/* Variable definitions can be made now. */
volatile rt_uint32_t eir, pk_counter;
volatile rt_bool_t rx_activiated;
。。。
/* TX Error handler */
if ((eir & EIR_TXERIF) != 0)
{
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF); <----- 这里也有处理代码,为何还有问题呢?
}
eir = spi_read(EIR);
// rt_kprintf("inner eir: 0x%08x\n", eir);
} while ((rx_activiated != RT_TRUE && eir != 0));
}
再查ENC28J60的文档,在官方的Errata文档(文档编号cn532750.pdf)找到了这样一句话:
12. Module: Transmit Logic
In Half-Duplex mode, a hardware transmission
abort caused by excessive collisions, a late collision
or excessive deferrals, may stall the internal
transmit logic. The next packet transmit initiated by
the host controller may never succeed
(ECON1.TXRTS will remain set indefinitely).
Work around
Before attempting to transmit a packet (setting
ECON1.TXRTS), reset the internal transmit logic
by setting ECON1.TXRST and then clearing
ECON1.TXRST. The host controller may wish to
issue this Reset before any packet is transmitted
(for simplicity), or it may wish to conditionally reset
the internal transmit logic based on the Transmit
Error Interrupt Flag (EIR.TXERIF), which will
become set whenever a transmit abort occurs.
Clearing ECON1.TXRST may cause a new transmit
error interrupt event (EIR.TXERIF will become
set). Therefore, the interrupt flag should be cleared
after the Reset is completed.
Google是这样翻译的
在半双工模式下,硬件传输
过多的冲突所造成的中止,后期碰撞
或过度推迟,可能会停止内部
发送逻辑。下一个数据包发送开始
主机控制器可能永远不会得逞
(ECON1.​​TXRTS仍将无限期设置)。
解决
试图发送一个数据包之前(设置
ECON1.​​TXRTS),复位内部传输逻辑
通过设置ECON1.​​TXRST,然后清除
ECON1.​​TXRST。主机控制器不妨
任何数据包传输之前发出此复位
(简单),或者它可能希望有条件地复位
基于发送的内部传输逻辑
错误中断标志(EIR.TXERIF),这将
成为集时中止发送时。
结算ECON1.​​TXRST可能导致一个新的发射
错误中断事件(EIR.TXERIF将成为
设置)。因此,应清除中断标志
复位完成后。
---------------------------------------------------------------
哦,原来是这的毛病,ENC28J60的内部发送逻辑停止了
于是,在中断服务程序中加了几句话
/* TX Error handler */
if ((eir & EIR_TXERIF) != 0)
{
//------------------------------------------------------------------------------------------- 添加开始
enc28j60_set_bank(ECON1);
spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
enc28j60_set_bank(EIR);
//------------------------------------------------------------------------------------------- 添加结束
spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF);
}
再测,可以了
只是网络速度稍微降了点,但仍有响应,负载过重时PING有TIMEOUT的现象,但一旦负载减轻,响应时间仍小于1mS
这估计就是困扰过好多网友的BUG吧 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|