Strange PHY input

Technical questions regarding the XTC tools and programming with XMOS.
Treczoks
Active Member
Posts: 38
Joined: Thu Mar 21, 2013 11:18 am

Strange PHY input

Post by Treczoks »

Hi!

My "Application" is still in its infancy, and it has a bunch of teething problems.

I've got the slicekit with the ether slice in the circle port. There is one process that generates packets, and another one that is supposed to receive them (via loopback cable).

Sadly, whatever I receive is not what I have sent. I send 37 U32 (unsigned 32-bit words) and I receive a lot less (28-29 U32)

At first, I compared the TXEN and the RXDV signals on the oscilloscope, and they looked ok.
Then I toggled a gpio port bin whenever I wrote to the TX_Data and it looked fine (320ns/32Bits).
But when I toggled another gpio port pin whenever I read an U32 from the RX_Data, I saw something odd: It took about 400ns/32Bits to read! RX_Clock was fine with 25MHz.

My receiver code looks like this:
1. Definition of the port structure:

Code: Select all

typedef struct MII_Receive_t {
	in buffered	port:32	RX_Data;
	in			port	RX_DataValid;
	in			port	RX_ClockPort;
	in			port	RX_Error;
	clock				RX_Clock;
}MII_Receive_t;
2. Defining the port:

Code: Select all

on stdcore[1]: MII_Receive_t Downlink_RX = {
	XS1_PORT_4E, XS1_PORT_1K, XS1_PORT_1J, XS1_PORT_1P, XS1_CLKBLK_1
};
3. Setting up the port:

Code: Select all

void ConfigReceive( MII_Receive_t &Port )
{
	configure_clock_src( Port.RX_Clock, Port.RX_ClockPort );
	configure_in_port( Port.RX_Data, Port.RX_Clock );
	configure_in_port( Port.RX_DataValid, Port.RX_Clock );
	configure_in_port_strobed_slave( Port.RX_Data, Port.RX_DataValid, Port.RX_Clock );
	start_clock( Port.RX_Clock );
}
4. The (dummy) receive function, which toggles the port bit 4B0 on every read and stores whatever it received.

Code: Select all

on stdcore[1]: out port DebugBits = XS1_PORT_4B;

#define DBG_MAXBUF	(40)
void DownlinkReceiver( MII_Receive_t &Port, chanend PacketTarget, chanend AudioTarget, chanend CommandTarget )
{
	unsigned DBG_Count;
	unsigned DBG_Count2;
	unsigned DBG_Buf[DBG_MAXBUF];
	unsigned PacketData;
	unsigned PacketValid;

	// If there is a packet currently in the pipe, wait it out.
	Port.RX_DataValid when pinseq(0) :> void;

	while(1){
		// As per book, wait for DataValid
		Port.RX_DataValid when pinsneq(0) :> PacketValid;
		// Wait for End-of-preamble
		Port.RX_Data when pinseq(0x0D) :> void;

		DBG_Count2 = DBG_Count;
		DBG_Count = 0;
		do{
			select{
				case Port.RX_Data :> PacketData:
					// A longword should have come here...
					// Store whatever we got
					if (DBG_Count<DBG_MAXBUF) DBG_Buf[DBG_Count] = PacketData;
					DBG_Count++;
					// Toggle Bit
					DebugBits <: DBG_Count;
					break;
				case Port.RX_DataValid when pinseq(0) :> PacketValid:
					// Packet ends.
					break;
			}
		} while( PacketValid );
	}
}
With this I get 28-29 toggles of 4B0, spaced 400ns apart. I've to admit that I'm new to XMOS processors, but this is derived from the XC manual MII receiver example, and I have no idea where this went downhill.

EDIT: The received packet is stored in DBG_Buf[], and it shows absolutely no resembly of the original packet. Added some comments.

Any help is appreciated.

Yours, Christian Treczoks


User avatar
andrew
Experienced Member
Posts: 114
Joined: Fri Dec 11, 2009 10:22 am

Post by andrew »

Without your whole project is is difficult to say exactly what is wrong but here are some suggestions:

Firstly, in the case

Code: Select all

  case Port.RX_DataValid when pinseq(0) :> PacketValid:
               // Packet ends.
  break;
You are best doing something like:

Code: Select all

 case Port.RX_DataValid when pinseq(0) :> PacketValid:
               // Packet ends.
               unsigned tail
               int taillen = endin(Port.RX_Data);
               Port.RX_Data :> tail;
               tail = tail >> (32 - taillen);
  break;
This will ensure if there was any data left in the RX_Data buffer when the RX_DataValid went low then it wont be left there for the future.

Secondly, I would set MAX_BUF to 381 and replace the following:

Code: Select all

if (DBG_Count<DBG_MAXBUF) DBG_Buf[DBG_Count] = PacketData;
               DBG_Count++;
               // Toggle Bit
               DebugBits <: DBG_Count;
with

Code: Select all

DBG_Buf[DBG_Count] = PacketData;
DBG_Count++;
Then at the end of the frame print the whole thing out(using xscope or otherwise) with

Code: Select all

printstrln("begin frame");
for(unsigned i=0;i< DBG_Count;i++) printhexln(DBG_Buf[i]);
I hope that helps. If not then you'll need to post more of you project.
Treczoks
Active Member
Posts: 38
Joined: Thu Mar 21, 2013 11:18 am

Post by Treczoks »

Hi!

Thanks for your reply, Andrew. I just returned from another project and can now put more time into this project again...
andrew wrote: Firstly, in the case

Code: Select all

  case Port.RX_DataValid when pinseq(0) :> PacketValid:
               // Packet ends.
  break;
You are best doing something like:

Code: Select all

 case Port.RX_DataValid when pinseq(0) :> PacketValid:
               // Packet ends.
               unsigned tail
               int taillen = endin(Port.RX_Data);
               Port.RX_Data :> tail;
               tail = tail >> (32 - taillen);
  break;
This will ensure if there was any data left in the RX_Data buffer when the RX_DataValid went low then it wont be left there for the future.
You are right on this one, data may be available directly after DataValid went down. I skipped this because my application does not produce byte-oriented packets but longword oriented packets (no internet or other Frame involved, this application is just abusing the ethernet PHY for its own purposes). My impression was that this code was intended to catch 1-3 octets (bytes) of data dangling in the input shift register.
Nonetheless, it does not explain why I only get part of the data, and the reception timing.
andrew wrote: Secondly, I would set MAX_BUF to 381 and replace the following:

Code: Select all

if (DBG_Count<DBG_MAXBUF) DBG_Buf[DBG_Count] = PacketData;
               DBG_Count++;
               // Toggle Bit
               DebugBits <: DBG_Count;
with

Code: Select all

DBG_Buf[DBG_Count] = PacketData;
DBG_Count++;
Then at the end of the frame print the whole thing out(using xscope or otherwise) with

Code: Select all

printstrln("begin frame");
for(unsigned i=0;i< DBG_Count;i++) printhexln(DBG_Buf[i]);
OK, but this only dumps the horribly wrong data I get ;-)
BTW, I would never leave that protective if-clause out of the picture in such a debug situation...
andrew wrote: I hope that helps. If not then you'll need to post more of you project.
OK, just tell me what files you need and how you want them. I will not post them here, though.

Yours, Christian
Treczoks
Active Member
Posts: 38
Joined: Thu Mar 21, 2013 11:18 am

Post by Treczoks »

Hi!
I just added that "endin()" construct without getting more data from it.
My sender still puts 37 longwords into the pipe with a nice regular TransmitEnable, and I get a similarly regular ReceiveDataValid, but the XMOS only sees 27 longwords of seemingly junk from the RX_Data port.

Yours, Christian
Treczoks
Active Member
Posts: 38
Joined: Thu Mar 21, 2013 11:18 am

Post by Treczoks »

Hi again,

I stripped my application down to the bone and put everything in a single source file to be able to attach it without giving anything away. And yes, the problem is still there...

Anyone out there with an idea where I goofed up?

Edit: I added some debug printing to it to see what I actually get on the receiver side. Looks totally different from what I see in the debugger - WHY?
I send 20+1 ints: 0, 1, 2, ..., 18, 19, Checksum:0x85ED10
I receive 13 ints: 1,2,4,5,7,9,10,12,13,15,17,18,0x85ED10
The 0, 3, 6, 8, 11, 14, 16 and 19 are missing.
Looks like the processor misses 3 out of 8 ints, even when all he has to do is store the data he receives in a simple array. There is really something fishy here. Other people get complete frames out of that thing, even when piping the data around.

Yours, Christian
You do not have the required permissions to view the files attached to this post.