Hello U-Boot users, I've been working on a custom board, based heavily on the Freescale MPC8349EMDS board. The only major difference is that the board has some FPGAs connected to the local bus.
I've found that the TSEC / gianfar ethernet does not work for me in 1000mbit mode. I constantly get "got error 4" from U-Boot, which means that a CRC error was detected by the TSEC controller. I have tried running the TSEC in 100mbit mode, without any problems. I can tftp as much data as I want in U-Boot, and I've transferred many, many gigabytes without issue in Linux. The problem is only with 1000mbit mode. I initially suspected problems with the PHY, a Marvell 88E1111. To diganose the problem, I set the PHY into loopback mode, then connected my logic analyzer to the PHY's RX lines. This removes the external network from the equation: I don't even have an ethernet cable connected. The logic analyzer traces show the correct, expected packet data coming from the PHY. By the time the TSEC copies the data into a buffer descriptor, the packet data has been corrupted. The problem is extra or missing bytes in the packet data. I have added some code to dump the packet contents on CRC error, and what I see in memory is not what the PHY sent. The corruption is not at a consistent offset in the packet. The number of extra or missing bytes is not always the same. The extra bytes that show up in the packet data seem like a FIFO issue to me. It is as if the internal FIFO reported that more data was available before the data was actually present. Something like that. For reference, here is what a memory dump of a good packet looks like. It has a length of 64 bytes. I have dumped 16 bytes past the end of the packet data. 0fffcbe0: ff ff ff ff ff ff ae dc 30 45 e8 3a 08 06 00 01 ........0E.:.... 0fffcbf0: 08 00 06 04 00 01 ae dc 30 45 e8 3a c0 a8 11 45 ........0E.:...E 0fffcc00: 00 00 00 00 00 00 c0 a8 11 39 00 00 00 00 00 00 .........9...... 0fffcc10: 00 00 00 00 00 00 00 00 00 00 00 00 2c d1 57 03 ............,.W. 0fffcc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ And this is what a bad packet looks like in memory. The length was reported by the TSEC as 64 bytes, but it was flagged as having a CRC error. Notice the extra bytes starting at 0x0fffcc0c, "copied" from 16 bytes earlier in the packet. The CRC is shifted 4 bytes in the packet due to the extra bytes. 0fffcbe0: ff ff ff ff ff ff ae dc 30 45 e8 3a 08 06 00 01 ........0E.:.... 0fffcbf0: 08 00 06 04 00 01 ae dc 30 45 e8 3a c0 a8 11 45 ........0E.:...E 0fffcc00: 00 00 00 00 00 00 c0 a8 11 39 00 00 c0 a8 11 45 .........9.....E 0fffcc10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0fffcc20: 2c d1 57 03 00 00 00 00 00 00 00 00 00 00 00 00 ,.W............. I have been running U-Boot and Linux on this board for >6 months. I've run plenty of stress tests, and I've been doing lots of work with the DMA controller. I've stressed the memory pretty hard, and I'm fairly confident that it is not a problem with RAM. The board has been perfectly stable. Other solutions I have tried, without any effect: * slowing down the core frequency from 528 -> 264 MHz * slowing down the RAM frequency from 266 -> 200 MHz I am unable to reproduce the corruption on my MPC8349EMDS eval board, but I'm running out of ideas to try and find the source of this problem. Has anyone seen anything like this before? Thanks for your help, Ira PS - Below is the patch of the debugging code I've added. diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 399116f..2f8f1bc 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -214,7 +214,9 @@ int tsec_init(struct eth_device *dev, bd_t * bd) startup_tsec(dev); /* If there's no link, fail */ - return (priv->link ? 0 : -1); + printf("LINK: %d\n", priv->link); + return 0; + //return (priv->link ? 0 : -1); } /* Writes the given phy's reg with value, using the specified MDIO regs */ @@ -928,22 +930,44 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length) return result; } +static unsigned char MYPACKET[4096]; + static int tsec_recv(struct eth_device *dev) { int length; struct tsec_private *priv = (struct tsec_private *)dev->priv; volatile tsec_t *regs = priv->regs; + u32 hwcrc, swcrc, cpcrc, rxaddr; while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { length = rtx.rxbd[rxIdx].length; + hwcrc = *(u32 *)(NetRxPackets[rxIdx] + length - 4); + memcpy(MYPACKET, NetRxPackets[rxIdx], length + 16); + swcrc = crc32(0, MYPACKET, length - 4); + swcrc = swab32(swcrc); + cpcrc = *(u32 *)(MYPACKET + length - 4); + + printf("CRC HW 0x%.8x SW 0x%.8x CP 0x%.8x IEVENT 0x%.8x MACCFG1 0x%.8x\n", + hwcrc, swcrc, cpcrc, regs->ievent, regs->maccfg1); + /* Send the packet up if there were no errors */ if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { NetReceive(NetRxPackets[rxIdx], length - 4); } else { - printf("Got error %x\n", - (rtx.rxbd[rxIdx].status & RXBD_STATS)); + rxaddr = (u32)NetRxPackets[rxIdx]; + printf("Got error %x\n", (rtx.rxbd[rxIdx].status & RXBD_STATS)); + printf("PACKET DATA START 0x%.8x END 0x%.8x LEN %d\n", rxaddr, rxaddr + length, length); + printf("RXIDX %d STAT 0x%.8x LEN %d\n", rxIdx, rtx.rxbd[rxIdx].status, length); + /* Print the buffer: + * $1: start address (for display purposes) + * $2: memory buffer to print + * $3: access mode (byte, short, word) + * $4: length to print + * $5: line length + */ + print_buffer(rxaddr, MYPACKET, 1, length + 16, 0); } rtx.rxbd[rxIdx].length = 0; diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h index 3c57403..1287829 100644 --- a/include/configs/MPC8349EMDS.h +++ b/include/configs/MPC8349EMDS.h @@ -53,6 +53,10 @@ #define CONFIG_83XX_PCICLK 66666666 /* in Hz */ #endif /* CONFIG_PCISLAVE */ +#define CONFIG_SYS_RX_ETH_BUFFER 16 +#define CONFIG_ARP_TIMEOUT 750UL +#define CONFIG_NET_RETRY_COUNT 64 + #ifndef CONFIG_SYS_CLK_FREQ #ifdef PCI_66M #define CONFIG_SYS_CLK_FREQ 66000000 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot