如题,gd407使用dm9000,当通讯一段时间后网络掉线,无法连接,程序未跑死,必须重启或者重新配置dm9000才能重新连接。经过排查之后,在dm9000的发送函数添加一小段延时解决
rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf *p)
{
uint64 tx_timestamp = 0;
int tx_status = 0;
DM9000_TRACE("dm9000 tx: %d\n", p->tot_len);
/* lock DM9000 device */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
/* disable dm9000a interrupt */
dm9000_io_write(DM9000_IMR, IMR_PAR);
/* Move data to DM9000 TX RAM */
DM9000_outb(DM9000_IO_BASE, DM9000_MWCMD);
{
/* q traverses through linked list of pbuf's
* This list MUST consist of a single packet ONLY */
struct pbuf *q;
rt_uint16_t pbuf_index = 0;
rt_uint8_t word[2], word_index = 0;
q = p;
/* Write data into dm9000a, two bytes at a time
* Handling pbuf's with odd number of bytes correctly
* No attempt to optimize for speed has been made */
while (q)
{
if (pbuf_index < q->len)
{
word[word_index++] = ((u8_t *)q->payload)[pbuf_index++];
if (word_index == 2)
{
DM9000_outw(DM9000_DATA_BASE, (word[1] << 8) | word[0]);
word_index = 0;
dm9000_delay(5); //添加小段延时,约2us
}
}
else
{
q = q->next;
pbuf_index = 0;
}
}
/* One byte could still be unsent */
if (word_index == 1)
{
DM9000_outw(DM9000_DATA_BASE, word[0]);
}
}
if (dm9000_device.packet_cnt == 0)
{
DM9000_TRACE("dm9000 tx: first packet\n");
dm9000_device.packet_cnt ++;
/* Set TX length to DM9000 */
dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff);
dm9000_io_write(DM9000_TXPLH, (p->tot_len >> 8) & 0xff);
/* Issue TX polling command */
dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
}
else
{
DM9000_TRACE("dm9000 tx: second packet\n");
dm9000_device.packet_cnt ++;
dm9000_device.queue_packet_len = p->tot_len;
}
/* enable dm9000a interrupt */
dm9000_io_write(DM9000_IMR, dm9000_device.imr_all);
/* unlock DM9000 device */
rt_sem_release(&sem_lock);
tx_timestamp = sys_timer_Getstamp();
/* transmit done */
while(1)
{
//rt_thread_delay(1);
dm9000_delay(5); //添加小段延时,约2us
tx_status = dm9000_io_read(DM9000_NSR); /* Got TX status */
if (tx_status & (NSR_TX2END | NSR_TX1END))
{
txcount++;
dm9000_device.packet_cnt --;
if (dm9000_device.packet_cnt > 0)
{
DM9000_TRACE("dm9000 isr: tx second packet\n");
/* transmit packet II */
/* Set TX length to DM9000 */
dm9000_io_write(DM9000_TXPLL, dm9000_device.queue_packet_len & 0xff);
dm9000_io_write(DM9000_TXPLH, (dm9000_device.queue_packet_len >> 8) & 0xff);
/* Issue TX polling command */
dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
}
break;
}
else
{
txrecount++;
if(sys_timer_getstamp_between(tx_timestamp) >= 20000)
{
dm9000_device.packet_txtimecout++;
dm9000_device.packet_cnt --;
if (dm9000_device.packet_cnt > 0)
{
DM9000_TRACE("dm9000 isr: tx second packet\n");
/* transmit packet II */
/* Set TX length to DM9000 */
dm9000_io_write(DM9000_TXPLL, dm9000_device.queue_packet_len & 0xff);
dm9000_io_write(DM9000_TXPLH, (dm9000_device.queue_packet_len >> 8) & 0xff);
/* Issue TX polling command */
dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
}
break;
}
}
}
DM9000_TRACE("dm9000 tx done\n");
return RT_EOK;
}