> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:ecos-discuss-
> [EMAIL PROTECTED] On Behalf Of Lambrecht Jürgen
> Sent: zondag 1 juni 2008 1:22
> To: Andrew Lunn; I-Yanaslov
> Cc: [EMAIL PROTECTED]
> Subject: RE: [ECOS] bugs in AT91 Ethernet driver
>
> Thanks for your replies.
>
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:ecos-discuss-
> > [EMAIL PROTECTED] On Behalf Of Andrew Lunn
> > Sent: zaterdag 31 mei 2008 14:04
> > To: I-Yanaslov
> > Cc: Andrew Lunn; [EMAIL PROTECTED]
> > Subject: Re: [ECOS] bugs in AT91 Ethernet driver
> >
> > On Sat, May 31, 2008 at 03:49:24PM +0400, I-Yanaslov wrote:
> > >
> > >> However, you are wrong about the TX buffers being on the heap. The
> > >> buffer is inside the at91_eth_priv_t structure. This is allocated
> at
> > >> the end of if_at91.c. It will be placed in the data segment.
> > >
> > > at91_eth_priv structure is contains only RX buffers, RX buffer
> > > descriptors and "TX buffer descriptors". No contains "TX buffers".
> > >
> > > at91_eth_send() shows " priv->tbd[priv->curr_tbd_idx].addr =
> > > sg_list[i].buf; " - no memory copy, only address assigment.
> > > But, sg_list[] it is mbuf, dynamically allocated in TCP/IP stack.
> >
> > Ah, OK. My error. That makes it more messy.
> >
> > How big is the SRAM on these ARM9 devices? 32K, 64K? If it is big
> > enough maybe we can move net_mbufs_area[] into the SRAM. Otherwise a
> > copy is needed for every packet to be transmitted.
> >
> The AT91SAM9620 has only 2 SRAMs of 4kB each.
> (The AT91SAM9621 has 160kB of SRAM, but no EMAC and LCD controller
> instead)
> So it will have to be the last option.
> To have a reliable driver, the fix is needed, but that (errata) is not
> why my TX does not work.
> The AT91SAM9620 errata is only valid at heavy network load (when there
> is RX and TX at the same time and then an SDRAM refresh or SDRAM bank
> opening or so). I only do a ping on a private network for test.
> And moreover, the Ethernet driver works in Redboot RAM (ok, not that
> well, 9% of the pings get lost).
>
> I will further debug tomorrow...
In attachment ' if_at91_jtagram_ecos1.01.06_sg1TXsram1.txt ' with a log.
It was compiled with if_at91.c patched as below.
You can see that at startup a gratuitous ARP is sent out, and I receive the
packet on my laptop with Wireshark.
The next TX (ARP reply as reply on RX of ARP request) is sent out by the TCP/IP
stack, but does not leave the board as I don't see it in Wireshark.
It gets stuck somewhere. Maybe the driver is waiting on something, or maybe the
TX DMA is blocked??
> And then copy every packet to SRAM before doing DMA...
>
In attachment my patch.
It contains
- in at91_eth_send(): modification (#ifdef SRAM1_ORIGIN) to copy sg_list[i].buf
first to internal SRAM, and only then do a DMA to the EMAC
- in at91_eth_recv(): bugfix described in previous mail
- general: I don't have a PHY attached but a switch. The MII is always up at
100Mbps, so no need to use SMI to read the link status in the phy registers. So
put '#ifdef PHY_PRESENT' around those parts of the code
I tested it with my AT91SAM9620-EK based board. And it works just as before
(see above).
Kind regards,
Juergen
«¬}¹Ñ}¥¹¥ÑuInit: mbinit(0x00000000)
[cyg_net_init] Init: cyg_net_init_devs(0x00000000)
Init device 'at91'
[cyg_net_init] Init: loopattach(0x00000000)
[cyg_net_init] Init: ifinit(0x00000000)
[cyg_net_init] Init: domaininit(0x00000000)
[cyg_net_init] Init: cyg_net_add_domain(0x200a71f8)
New domain internet at 0x00000000
[cyg_net_init] Init: cyg_net_add_domain(0x200a6ba8)
New domain route at 0x00000000
[cyg_net_init] Init: call_route_init(0x00000000)
[cyg_net_init] Done
Televic Echo-Test Application
Juergen Lambrecht, 1.09.11, built 21:45:42, Jun 1 2008
BOOTP[eth0] op: REPLY
htype: Ethernet
hlen: 6
hops: 0
xid: 0x0
secs: 0
flags: 0x0
hw_addr: 00:0e:3d:01:03:00
client IP: 10.0.54.249
my IP: 10.0.54.249
server IP: 10.0.56.4
gateway IP: 10.0.127.254
options:
subnet mask: 255.255.0.0
IP broadcast: 10.0.255.255
gateway: 10.0.127.254
Sending 42 bytes
xmit 42 bytes at 0x200fd856 sg[1] //JL: I see this
packet in Wireshark
200FD856: FF FF FF FF FF FF 00 0E 3D 01 03 00 08 06 00 01 |........=.......|
200FD866: 08 00 06 04 00 01 00 0E 3D 01 03 00 0A 00 36 F9 |........=.....6.|
200FD876: 00 00 00 00 00 00 0A 00 36 F9 |........6. |
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
End of initializations
rx 14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D 09 B4 CA 6A 08 06 |...........j.. |
rx 50 bytes at 200fd82c sg[1]
200FD82C: 00 01 08 00 06 04 00 01 00 1D 09 B4 CA 6A 0A 00 |.............j..|
200FD83C: 38 31 00 00 00 00 00 00 0A 00 36 F9 00 00 00 00 |81........6.....|
200FD84C: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DE 09 |................|
200FD85C: EC 66 |.f |
Sending 42 bytes
xmit 42 bytes at 0x200fd7d6 sg[1] //JL: I DONT see
this packet in Wireshark??
200FD7D6: FF FF FF FF FF FF 00 0E 3D 01 03 00 08 06 00 01 |........=.......|
200FD7E6: 08 00 06 04 00 01 00 0E 3D 01 03 00 0A 00 36 F9 |........=.....6.|
200FD7F6: 00 00 00 00 00 00 0A 00 36 F9 |........6. |
rx 14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D 09 B4 CA 6A 08 06 |...........j.. |
rx 50 bytes at 200fd6ac sg[1]
200FD6AC: 00 01 08 00 06 04 00 01 00 1D 09 B4 CA 6A 0A 00 |.............j..|
200FD6BC: 38 31 00 00 00 00 00 00 0A 00 36 F9 00 00 00 00 |81........6.....|
200FD6CC: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DE 09 |................|
200FD6DC: EC 66 |.f |
.14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D 09 B4 CA 6A 08 00 |...........j.. |
rx 244 bytes at 2011e7c8 sg[1]
2011E7C8: 45 00 00 F0 B3 BE 00 00 80 11 3A 0E 0A 00 38 31 |E.........:...81|
2011E7D8: 0A 00 FF FF 00 8A 00 8A 00 DC D3 B8 11 0E 81 14 |................|
2011E7E8: 0A 00 38 31 00 8A 00 C6 00 00 20 46 45 45 4D 46 |..81...... FEEMF|
2011E7F8: 47 43 4E 46 45 46 45 46 44 43 4E 45 4B 45 4D 44 |GCNFEFEFDCNEKEMD|
2011E808: 42 43 41 43 41 43 41 43 41 41 41 00 20 41 42 41 |BCACACACAAA. ABA|
2011E818: 43 46 50 46 50 45 4E 46 44 45 43 46 43 45 50 46 |CFPFPENFDECFCEPF|
2011E828: 48 46 44 45 46 46 50 46 50 41 43 41 42 00 FF 53 |HFDEFFPFPACAB..S|
2011E838: 4D 42 25 00 00 00 00 00 00 00 00 00 00 00 00 00 |MB%.............|
2011E848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 11 00 |................|
2011E858: 00 2C 00 00 00 00 00 00 00 00 00 E8 03 00 00 00 |.,..............|
2011E868: 00 00 00 00 00 2C 00 56 00 03 00 01 00 01 00 02 |.....,.V........|
2011E878: 00 3D 00 5C 4D 41 49 4C 53 4C 4F 54 5C 42 52 4F |.=.\MAILSLOT\BRO|
2011E888: 57 53 45 00 0C 00 E0 93 04 00 54 45 4C 45 56 49 |WSE.......TELEVI|
2011E898: 43 00 00 00 C8 35 11 00 00 10 03 0A 00 10 00 80 |C....5..........|
2011E8A8: 00 10 F8 7F 54 4C 56 2D 54 54 53 2D 4A 4C 31 00 |....TLV-TTS-JL1.|
2011E8B8: B9 81 0D 08 |.... |
--- F:\version_ecos\packages\devs\eth\arm\at91\current\src\if_at91.c
2008-03-07 08:35:36.000000000 +-0200
+++ F:\ecos_ronetix\packages\devs\eth\arm\at91\current\src\if_at91.c
2008-06-01 23:09:54.000000000 +-0200
@@ -64,13 +66,15 @@
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/diag.h>
#include <cyg/io/eth/netdev.h>
#include <cyg/io/eth/eth_drv.h>
#include <cyg/io/eth/eth_drv_stats.h>
+#ifdef PHY_PRESENT
#include <cyg/io/eth_phy.h>
+#endif
#include <errno.h>
#include <string.h>
// Set up the level of debug output
#if CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL > 0
#define debug1_printf(args...) diag_printf(args)
@@ -165,13 +169,15 @@
typedef struct at91_eth_priv_s
{
cyg_uint32 intr_vector;
char *esa_key; // RedBoot 'key' for device ESA
cyg_uint8 *enaddr;
cyg_uint32 base; // Base address of device
+#ifdef PHY_PRESENT
eth_phy_access_t *phy;
+#endif
rbd_t rbd[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS];
rb_t rb[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS];
tbd_t tbd[CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS];
unsigned long curr_tx_key;
cyg_bool tx_busy;
cyg_uint32 last_tbd_idx;
@@ -298,18 +304,19 @@
CYG_FAIL("Unable to program MII clock");
}
HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_NCFG, cfg);
}
-
+#ifdef PHY_PRESENT
ETH_PHY_REG_LEVEL_ACCESS_FUNS(at91_phy,
at91_init_phy,
NULL,
at91_write_phy,
at91_read_phy);
-
+#endif
//======================================================================
// Receiver buffer handling
// Initialize the receiver buffers and descriptors
static void
at91_rb_init(at91_eth_priv_t *priv)
@@ -482,13 +489,15 @@
{
struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
bool esa_ok = false;
unsigned char enaddr[6] = { CYGPKG_DEVS_ETH_ARM_AT91_MACADDR};
unsigned char enzero[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+#ifdef PHY_PRESENT
unsigned short phy_state = 0;
+#endif
cyg_uint32 ncfg = 0;
debug1_printf("\nAT91_ETH: Initialising @ %x\n",priv->base);
priv->tx_busy = false;
priv->curr_tbd_idx = 0;
@@ -557,57 +566,64 @@
// Setup the transmit descriptors
at91_tb_init(priv);
// And tell the EMAC where the first transmit buffer descriptor is
HAL_WRITE_UINT32(priv->base + AT91_EMAC_TBQP, (cyg_uint32)priv->tbd);
+#ifdef PHY_PRESENT
// Setup the PHY
CYG_ASSERTC(priv->phy);
at91_mdio_enable();
if (!_eth_phy_init(priv->phy))
{
at91_mdio_disable();
+ debug2_printf("_eth_phy_init failed\n");
return (false);
}
// Get the current mode and print it
phy_state = _eth_phy_state(priv->phy);
+#endif
at91_mdio_disable();
HAL_READ_UINT32(priv->base + AT91_EMAC_NCFG,ncfg);
-
+#ifdef PHY_PRESENT
if ((phy_state & ETH_PHY_STAT_LINK) != 0)
{
if (((phy_state & ETH_PHY_STAT_100MB) != 0))
{
debug1_printf("AT91_ETH: 100Mbyte/s");
+#endif
ncfg |= AT91_EMAC_NCFG_SPD_100Mbps;
+#ifdef PHY_PRESENT
}
else
{
debug1_printf("AT91_ETH: 10Mbyte/s");
ncfg &= ~(AT91_EMAC_NCFG_SPD_100Mbps);
}
if((phy_state & ETH_PHY_STAT_FDX))
{
debug1_printf(" Full Duplex\n");
+#endif
ncfg |= AT91_EMAC_NCFG_FD;
+#ifdef PHY_PRESENT
}
else
{
debug1_printf(" Half Duplex\n");
ncfg &= ~(AT91_EMAC_NCFG_FD);
}
}
else
{
debug1_printf("AT91_ETH: No Link\n");
}
-
+#endif
//Setup the network configuration
ncfg |= (AT91_EMAC_NCFG_RLCE);
HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCFG,ncfg);
@@ -721,20 +737,27 @@
at91_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
int total_len, unsigned long key)
{
at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
int i;
cyg_uint32 sr;
-
+#ifdef SRAM1_ORIGIN /* define it in plf_io.h if present */
+ cyg_uint32 total_bytes = 0; /* position in SRAM1 */
+#endif
priv->tx_busy = true;
priv->last_tbd_idx = priv->curr_tbd_idx;
for(i = 0;i<sg_len;i++)
{
+#ifdef SRAM1_ORIGIN
+ memcpy((cyg_uint8 *)(SRAM1_ORIGIN+total_bytes), (cyg_uint8
*)(sg_list[i].buf), sg_list[i].len);
+ priv->tbd[priv->curr_tbd_idx].addr = SRAM1_ORIGIN+total_bytes;
+#else
priv->tbd[priv->curr_tbd_idx].addr = sg_list[i].buf;
+#endif
sr = (sg_list[i].len & AT91_EMAC_TBD_SR_LEN_MASK);
// Set the End Of Frame bit in the last descriptor
if(i == (sg_len-1))
{
sr |= AT91_EMAC_TBD_SR_EOF;
@@ -747,12 +770,15 @@
}
else
{
priv->tbd[priv->curr_tbd_idx].sr = (sr | AT91_EMAC_TBD_SR_WRAP);
priv->curr_tbd_idx = 0;
}
+#ifdef SRAM1_ORIGIN
+ total_bytes += sg_list[i].len;
+#endif
}
// Store away the key for when the transmit has completed
// and we need to tell the stack which transmit has completed.
priv->curr_tx_key = key;
@@ -936,19 +962,22 @@
cyg_uint32 total_bytes = 0;
for(i = 0;i<sg_len;i++)
{
+ bytes_in_list = 0; /* go to next list */
while(bytes_in_list < sg_list[i].len)
{
bytes_needed_list = sg_list[i].len - bytes_in_list;
if(priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_EOF)
{
bytes_in_buffer =
((priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_LEN_MASK)
- - total_bytes) - buffer_pos;
+ - total_bytes);
}
else
{
bytes_in_buffer = AT91_EMAC_RX_BUFF_SIZE - buffer_pos;
}
@@ -1001,14 +1030,17 @@
return(CYGNUM_HAL_INTERRUPT_EMAC);
}
at91_eth_priv_t at91_priv_data =
{
.intr_vector = CYGNUM_HAL_INTERRUPT_EMAC,
- .base = AT91_EMAC,
+ .base = AT91_EMAC
+#ifdef PHY_PRESENT
+ ,
.phy = &at91_phy
+#endif
};
ETH_DRV_SC(at91_sc,
&at91_priv_data, // Driver specific data
"eth0", // Name for this interface
at91_eth_start,
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss