[ECOS] "packets eaten" with AT91 EMAC Ethernet driver
Jürgen Lambrecht
J.Lambrecht@televic.com
Tue Jun 10 16:11:00 GMT 2008
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
More information about the Ecos-discuss
mailing list