MCF52235 - FEC buffer ring

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCF52235 - FEC buffer ring

5,129 Views
BIS
Contributor I
Hello.
I have problem with FEC driver creation. I use mcf52235. I've discovered that problem in FEC driver's buffers. I've simplified driver and now it's just initialization function. Here is definitions:
 
// defines
#define FEC_BUF_SIZE 256              // buffer size
#define N_TX_BUF 16                        // number of buffers
#define N_RX_BUF 16
// variables
#pragma pack(1)
typedef struct {
 volatile unsigned short status;
 volatile unsigned short length;
 volatile char *buffer;
} FEC_BUF_DESC;
#pragma pack()
 
char desc[sizeof(FEC_BUF_DESC)*(N_RX_BUF+N_TX_BUF)+15];
char txBuffer[N_TX_BUF*FEC_BUF_SIZE+15];
char rxBuffer[N_RX_BUF*FEC_BUF_SIZE+15];
FEC_BUF_DESC *pRXBD;
FEC_BUF_DESC *pTXBD;
char *pch;                              // tmp
// code
 pRXBD = (FEC_BUF_DESC *)(((long)desc+15)&0xFFFFFFF0);              // pointer to BD-rx-ring
 pTXBD = pRXBD + N_RX_BUF;                                                                  // pointer to BD-tx-ring
 MCF_FEC_EMRBR = FEC_BUF_SIZE;
 MCF_FEC_ERDSR = (unsigned long)pRXBD;
 MCF_FEC_ETDSR = (unsigned long)pTXBD;
 pch = (char *)(((long)rxBuffer+15)&0xFFFFFFF0);                                     // rx data buffer
 for ( i = 0; i < N_RX_BUF; ++i ) {
  pRXBD[i].status = MCF_FEC_RxBD_E;
  pRXBD[i].buffer = pch+i*FEC_BUF_SIZE;
 }
 pRXBD[N_RX_BUF-1].status |= MCF_FEC_RxBD_W;                             // tx data buffer
 pch = (char *)(((long)txBuffer+15)&0xFFFFFFF0);
 for ( i = 0; i < N_TX_BUF; ++i ) {
  pTXBD[i].status = 0;
  pTXBD[i].buffer = pch+i*FEC_BUF_SIZE;
 }
 pTXBD[N_TX_BUF-1].status |= MCF_FEC_TxBD_W;
 
This is map-file:
 
  20002370 0000100F .bss    txBuffer (fec.c)
  20003380 0000100F .bss    rxBuffer (fec.c)
  20004390 0000010F .bss    desc (fec.c)
Somehow happens that FEC fills rxBuffer and damages desc also. After that data memory corrupts and my program makes many miracles. I'm sure that problem in memory corruption, I've spent halfweek for searching. Here are several notes:
1. If I exchange memory locations of rxBuffer and txBuffer program works fine. I've simplified program and it doesn't use txBuffer. Array desc isn't corrupted.
2. If I initialize all pointers and registers but don't enable FEC (ETHER_EN) program works fine. FEC doesn't fork but it hasn't miracles.
3. If I remove simplification FEC driver works fine during short time. Just before miracles starts.
4. if I set FEC_BUF_SIZE equal 1520 (1 frame/buffer) program works fine. No miracles at all.
 
I just cannot find problems in my buffer's configuration. Help me please.
 
BIS



--
Alban Edit: Please always include FSL Part Number in Message Subject line.

 


Message Edited by Alban on 2007-09-07 03:07 PM
Labels (1)
0 Kudos
10 Replies

716 Views
mccPaul
Contributor I
Hi
 
It doesn't look like you are setting the length of the buffers in the buffer descriptor rings, so they could be set to anything and this is why you are getting a buffer overrun.
 
You need to add something like:
 
pRXBD[i].length= FEC_BUF_SIZE;
 
and
 
pTXBD[i].length= FEC_BUF_SIZE;
 
Although the FEC allows for scatter/gather RX buffers, you will probably end up with a much more effective FEC driver if your RX buffers are big enough to contain an entire frame. This means that the RX buffers should be 1536 bytes long for normal frames. The FEC truncates any frame longer than 2047 bytes, so 2KB buffers are guaranteed to be large enough for any frame.
 
If you are concerned about memory usage you either need to use fewer RX buffers, or follow the example of the Coldfire_lite stack that has a pool of large and small buffers that are shared between the TX and RX parts of the driver.
 
Paul.
0 Kudos

716 Views
BIS
Contributor I
Hi, mccp
 
I don't agree to initialize field BD.length in FEC initialization. I'll initialize pTXBD[i].length just before frame transmittion. FEC'll overwrite pRXBD[i].length during frame transition from its internal buffer to rxBuffer. Buffer size is specified in MCF_FEC_EMRBR.
 
My program is complex enough. I cannot allow 1536-bytes buffers. I can have 8 1536-bytes buffers at all. It's not effective memory usage.
 
BIS
0 Kudos

716 Views
mccPaul
Contributor I
Hi
 
Sorry - didn't look closely enough, you are correct!
 
It looks as though the configuration is fine, maybe it is being overwritten elsewhere? Can you post your RX and TX interupt handler code?
 
Paul.
0 Kudos

716 Views
BIS
Contributor I
I haven't interrupt code for FEC. Mask register MCF_FEC_EIMR = 0. I don't process incoming frames at all. FEC should fill my buffer. FEC must not write in full buffer. Actually rxed buffer is not completely full. It contains 16 small buffers. Miracles starts when 12 buffers are filled usually. Sometimes it happens even earlier.
 
I've returned functionality to my program. I have workable code now. Here is buffers declaration:
 
char desc[sizeof(FEC_BUF_DESC)*(N_RX_BUF+N_TX_BUF)+15];
char rxBuffer[N_RX_BUF*FEC_BUF_SIZE+15];
char unused2[N_RX_BUF*FEC_BUF_SIZE+15]; // memory bug
char txBuffer[N_TX_BUF*FEC_BUF_SIZE+15];
char unused3[N_RX_BUF*FEC_BUF_SIZE+15]; // memory bug
FEC_BUF_DESC *pRXBD;
FEC_BUF_DESC *pTXBD;
Here is map-file:
 
  2000285E 00000004 .bss    pTXBD (fec.c)
  20002862 00000004 .bss    pRXBD (fec.c)
  20002866 0000080F .bss    unused3 (fec.c)
  20003076 0000080F .bss    txBuffer (fec.c)
  20003886 0000080F .bss    unused2 (fec.c)
  20004096 0000080F .bss    rxBuffer (fec.c)
  200048A6 0000008F .bss    desc (fec.c)
I test my TCP/IP stack now. My test is sequence of PINGs. I have 100 frames - no problems with my TCP/IP stack. But I cannot remove buffers unused2 and unused3. I don't use these buffers. I just initialize some their items to bypass compiler memory optimization. I have my old miracles if I remove declaration of unused2 or unused3. I didn't play with size of these buffers.
 
BIS
0 Kudos

716 Views
mccPaul
Contributor I
Hi
 
Ok, so you have code that initialises the FEC and then does no further processing? Do you just set ETHER_EN and then write RDAR? I assume that you don't write TDAR.
 
What is the data that is written into your receive buffers by the FEC? Do the sizes of the data written to the rx BD.length make sense? And do the flags in the buffer descriptors also make sense?
 
I am interested in knowing what the data is that is overflowing your receive buffer ring.
 
Paul.
0 Kudos

716 Views
BIS
Contributor I
Hi Paul.
 
I initialised FEC without further processing. I set RDAT and TDAR after enabling FEC (set ETHER_EN).  Received packets were broadcast flow in LAN. I've made several tests:
1. I printed source, destination and protocol fields of received frames - common information. Our LAN has a plenty of broadcast IP and ARP packets :smileyhappy:
2. I polled bit E in BD.status for every buffer. I a single row I've printed empty/filled status for all BDs. That's how I've got that memory corrupts when 12 buffer are filled. I haven't analyzed BD.length. I'm going to do that.
 
BIS
0 Kudos

716 Views
BIS
Contributor I
I've tested stored fields BD.length. Buffer sizes are correct. I've played with length of "unused" arrays also. Look here:
 
char rxBuffer[N_RX_BUF*FEC_BUF_SIZE+15];
char unused2[SZ]; // memory bug
char txBuffer[N_TX_BUF*FEC_BUF_SIZE+15];
char unused3[SZ]; // memory bug
I've tested values of SZ are alowed. I'm not completely sure but I have idea:
sizeof(rxBuffer + unused2) mod 0x3A = 0
sizeof(txBuffer + unused3) mod 0x3A = 0
 
I mean that "unused" arrays are like padding and whole size of array plus buffer must be 0x3A-bytes aligned. I have no miracles if size is 0x3A-bytes aligned. I don't know physical or logical meaning of this number.
 
BIS
0 Kudos

716 Views
theJoel
Contributor III
Hello BIS,

This could be a similar hardware bug we encountered in the ColdFire V2 FEC.

From the MCF5271 Device Errata:

3 FEC Receive Buffer Overrun in 10BaseT Mode

3.1 Description
When the FEC is connected to a 10BaseT network and if length of the data stored in a descriptor is not evenly divisible by 16 (not line-aligned), then the FEC will write extra lines at the end of the buffer—the entire line that contains the last valid data is written and at least one extra line, but up to four additional lines after the end of the valid data can also be written. In most cases this is not a problem, since the extra lines of data still fall within the limits of the buffer. However, if the valid data ends near the end of the buffer, then the extra lines written by the FEC might be outside of the data buffer. This leads to corruption of the next buffer, descriptor, data, or code stored in the adjacent memory.
For example, as shown in Figure 1, if the max buffer size is programmed to 0x600 and a frame that is 0x5F8 bytes long is received, then a line is written starting at buffer start + 0x5F0. The first half of the line at buffer start + 0x5F0 is valid frame data that should be processed by the FEC driver; the second half of the line is additional data that is written because the FEC will only write complete lines. This data should be ignored by the FEC driver. So far, this is correct FEC behavior as originally specified. However, the FEC will repeat the last line of valid data a number of times. The line at buffer start + 0x600 will be written, and as many as three additional lines beyond the end of the data buffer could be written.

[fig not included :smileysad: ]
Figure 1. Buffer Overrun Example


3.2 Workaround

There are three independent workarounds:
1. Only use 100BaseT.
2. Allocate extra lines for the receive data buffers. The actual allocated memory for each buffer should be equal to the receive buffer size programmed in the FEC’s EMRBR register plus four lines (16 byte-sized lines).
3. Program the data buffer size one line larger than the max packet size (data buffer size = EMRBR + 0x40).


I know this is fixed in a newer rev of the 5271 processor, but thought it might be relevant.

Regards,
Joel.
0 Kudos

716 Views
BIS
Contributor I
OK, guys, problem is solved. I've found "lucky" alignment in previous tests. I've found today that that alignment isn't lucky for all frames. It's lucky for PING packets with 32 bytes of data and is not for PING packets with 1000 bytes of data.
 
Memory corruption was discovered quickly but it happened not because of FEC error activity or my misunderstanding. Part of SRAM was spent to stack in my project. Ethernet buffers were too big and intersected with stack area. BD's ring was in stack area too. It was the source of problem.
 
Paul, Joel, thank you for your time.
 
BIS
0 Kudos

716 Views
mccPaul
Contributor I
It's always good to find the bug!
 
Paul.
0 Kudos