This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: "packets eaten" with AT91 EMAC Ethernet driver
- From: Jürgen Lambrecht <J dot Lambrecht at televic dot com>
- To: ecos-discuss at ecos dot sourceware dot org
- Cc: Andrew Lunn <andrew at lunn dot ch>, I-Yanaslov <yanaslov_iv at ic-bresler dot ru>
- Date: Tue, 10 Jun 2008 18:11:25 +0200
- Subject: Re: [ECOS] "packets eaten" with AT91 EMAC Ethernet driver
- References: <369C2E4EDB94C34881A8178BEA192A124DA9@nt-email.TELEVIC.COM>
Lambrecht Jürgen wrote:
-----Original Message-----
From: Andrew Lunn [mailto:andrew@lunn.ch]
Sent: maandag 9 juni 2008 17:32
To: Lambrecht Jürgen
Cc: ecos-discuss@ecos.sourceware.org; I-Yanaslov
Subject: Re: [ECOS] "packets eaten" with AT91 EMAC Ethernet driver
On Mon, Jun 09, 2008 at 05:19:02PM +0200, J?rgen Lambrecht wrote:
Hello,
Since I solved the bugs in the AT91 EMAC driver
(RX: reset of ?bytes_in_list? (position in current sg_list))(TX: at
TXERR IRQ, reset SW pointer; set all used bits to 0 instead of 1),
I always had the same problem: after a while of communicating over
Ethernet with the AT91 EMAC, packets get ?eaten?.
TX Packets get stuck, and they need an RX packet to get out.
It sounds like missed interrupts, or a race condition in the interrupt
handling.
Yes indeed.
The original driver does not mask interrupts at the start of the ISR and unmask them at the end of the DSR.
Is it correct that this mask/unmask is not needed because it is an internal interrupt and at the end of the ISR 'cyg_interrupt_acknowledge(vector)' is called - this acknowledge clears the interrupt? So this should be ok.
Maybe there is a sort of race condition with can_send()?
Indeed, that was the problem:
Wrong code in at91_eth_deliver():
if (tsr&AT91_EMAC_TSR_COMP) //5
{
at91_reset_tbd(priv);
_eth_drv_tx_done(sc,priv->curr_tx_key,0);
priv->tx_busy = false;
}
Correct code:
{
at91_reset_tbd(priv, b_reset_tbd_idx);
priv->tx_busy = false;
_eth_drv_tx_done(sc,priv->curr_tx_key,0);
}
Aparantly very few people know how the complete TCP/IP stack works in
eCos.... I also did not knew it, now I know:
The high-level TCP/IP stack puts al its data in a buffer, and calls once
the "middleware" /io/eth/current/src/net/eth_drv.c::eth_drv_send() function.
If the low-level driver is available (can_send() returns not zero) then
the first packet is sent.
If the low-level driver is not available it stops here. It is supposed
that the low-level driver will inform then the middleware when it is
ready by calling tx_done.
eth_drv_tx_done on its turn calls eth_drv_send() which then checks again
can_send()
The AT91 driver first called tx_done, calling send calling can_send
which returns 0 of course.
And afterwards - too late - busy is set to true, so that can_send can
return 1...
Missing a TX interrupt is fatal..
Then the option CYGPKG_NET_FAST_THREAD_TICKLE_DEVS is very handy
(default on option!)! But this unblocks only an already blocked driver..
Mark that for LW-IP and Redboot there are other drivers there.
Kind regards,
Jürgen
P.S.: my troubles are not yet finished; I have RX BNA problems now..
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss