This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: "packets eaten" with AT91 EMAC Ethernet driver


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]