Troubleshooting XLink Code between custom boards

Technical questions regarding the XTC tools and programming with XMOS.
DrNO
Member++
Posts: 31
Joined: Mon Feb 06, 2012 11:42 pm

Troubleshooting XLink Code between custom boards

Post by DrNO »

Hello All,
I'll be honest, even after going through the "Tools User Guide" the creation/tweaking of XN files escapes me. I'm trying to do something pretty basic, continuously send a packet back and forth between to XS-L1 Custom boards. The program compiles but when I scope pins 52-55 on the 1st board with my Saleae I get nothing. Would someone be willing to take a look at my XN file and code to see if I'm on the right track? I'm almost positive the problem is in setting up the links in my XN file. Any help is greatly appreciated!

Additionally, does anyone know where I can get a detailed datasheet on the XLINK protocol including timing diagrams and the process to initialize/release the links?


SystemLayout.JPG


MAIN.XC

Code: Select all

#include <platform.h>
#include <xs1.h>
#include <print.h>

// Xcore 0 Ports


void XlinkTrans (chanend INTO, chanend OutOf)
{
	unsigned int time;
	timer t;
	unsigned tmp;

	while(1)
	{
		t :> time;
		select
		{
			case INTO :> tmp: // wait for message from another core
			{
				t when timerafter(time + 5000) :> time;
				OutOf <: tmp;

				break;
			}
		}
	}
}

void main(void)
{
	chan Chans[2];
	par
	{
		on stdcore [0]: {
			Chans[0] <: 1;
			XlinkTrans(Chans[1], Chans[0]);
		}
		on stdcore [1]: XlinkTrans(Chans[0], Chans[1]);

	}
}

The XN File

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
  <Type>Board</Type>

  <Declarations>
    <Declaration>core stdcore[2]</Declaration>
  </Declarations>

 <Packages>
 <Package Type="XS1-L1A-TQ48" Id="whatever">
  <Nodes>
    <Node InPackageId="0" Type="XS1-L1A" id="0" oscillator="13Mhz" systemfrequency="500MHz" referencefrequency="100MHz">
          <Core Number="0" Reference="stdcore[0]">
            <Port Location="XS1_PORT_1A" Name="PORT_SPI_MISO"/>
            <Port Location="XS1_PORT_1B" Name="PORT_SPI_SS"/>
            <Port Location="XS1_PORT_1C" Name="PORT_SPI_CLK"/>
            <Port Location="XS1_PORT_1D" Name="PORT_SPI_MOSI"/>
            <Port Name="UIFM_INT_CLK_PORT" Location="XS1_PORT_1I"/>
        	<Port Name="UIFM_USB_CLK_PORT" Location="XS1_PORT_1H"/>
        	<Port Name="UIFM_REG_WRITE_PORT" Location="XS1_PORT_8C"/>     
        	<Port Name="UIFM_REG_READ_PORT"  Location="XS1_PORT_8D"/> 
        	<Port Name="UIFM_FLAG_0_PORT"    Location="XS1_PORT_1N"/>       
        	<Port Name="UIFM_FLAG_1_PORT"    Location="XS1_PORT_1O"/>
        	<Port Name="UIFM_FLAG_2_PORT"    Location="XS1_PORT_1P"/>
        	<Port Name="UIFM_TX_DATA_PORT"   Location="XS1_PORT_8A"/>
        	<Port Name="UIFM_RX_DATA_PORT"   Location="XS1_PORT_8B"/>
        	<Port Name="UIFM_STP_SUS_PORT"   Location="XS1_PORT_1E"/>
        	<Port Name="UIFM_LS_PORT"        Location="XS1_PORT_4D"/>
          </Core>
    </Node></Nodes>
 </Package>
 <Package Type="XS1-L1A-TQ48" Id="whatever1">
  <Nodes>
    <Node InPackageId="0" Type="XS1-L1A" id="1" oscillator="13Mhz" systemfrequency="500MHz" referencefrequency="100MHz">
          <Core Number="0" Reference="stdcore[1]">
            <Port Location="XS1_PORT_1A" Name="PORT_SPI_MISO" />
            <Port Location="XS1_PORT_1B" Name="PORT_SPI_SS" />
            <Port Location="XS1_PORT_1C" Name="PORT_SPI_CLK" />
            <Port Location="XS1_PORT_1D" Name="PORT_SPI_MOSI" />
            <Port Name="UIFM_INT_CLK_PORT" Location="XS1_PORT_1I" />
        	<Port Name="UIFM_USB_CLK_PORT" Location="XS1_PORT_1H" />
        	<Port Name="UIFM_REG_WRITE_PORT" Location="XS1_PORT_8C" />     
        	<Port Name="UIFM_REG_READ_PORT" Location="XS1_PORT_8D" /> 
        	<Port Name="UIFM_FLAG_0_PORT" Location="XS1_PORT_1N" />       
        	<Port Name="UIFM_FLAG_1_PORT" Location="XS1_PORT_1O" />
        	<Port Name="UIFM_FLAG_2_PORT" Location="XS1_PORT_1P" />
        	<Port Name="UIFM_TX_DATA_PORT" Location="XS1_PORT_8A" />
        	<Port Name="UIFM_RX_DATA_PORT" Location="XS1_PORT_8B" />
        	<Port Name="UIFM_STP_SUS_PORT" Location="XS1_PORT_1E" />
        	<Port Name="UIFM_LS_PORT" Location="XS1_PORT_4D" />
          </Core>
    </Node></Nodes>
 </Package></Packages>

  <Links>
  <Link Encoding="2wire" Delays="15,15">
      <LinkEndpoint NodeId="0" Link="X0LC" />
      <LinkEndpoint NodeId="1" Link="X0LB" />
    </Link></Links>

  <ExternalDevices>
    <Device Nodeid="0" Core="0" Class="SPIFlash" Name="bootFlash" Type="W25X40">
      <Attribute Name="PORT_SPI_MISO" Value="PORT_SPI_MISO"/>
      <Attribute Name="PORT_SPI_SS"   Value="PORT_SPI_SS"/>
      <Attribute Name="PORT_SPI_CLK"  Value="PORT_SPI_CLK"/>
      <Attribute Name="PORT_SPI_MOSI" Value="PORT_SPI_MOSI"/>
    </Device>
  </ExternalDevices>

  <JTAGChain>
  <JTAGDevice NodeId="0" Position="0" /><JTAGDevice NodeId="1" Position="1" /></JTAGChain>

</Network>
You do not have the required permissions to view the files attached to this post.


Guest

Post by Guest »

Hi DrNo,
You missed boot and boote information. In XN file you should specify where the chip has to boot from. They should be something similar to this,

In Node 0:
------------
<Boot >
<Source Location ="SPI : bootFlash "/>
<Bootee NodeId =" Slave " Core ="0"/>
</Boot >

In Node 1:
------------
<Boot >
<Source Location =" XMOSLINK "/>
</Boot >

More information is available in Platform configurations ection of tools user guide,
https://www.xmos.com/download/public/To ... 13E%29.pdf

-Sethu
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

DrNO wrote:Additionally, does anyone know where I can get a detailed datasheet on the XLINK protocol including timing diagrams and the process to initialize/release the links?
Timing diagrams? There is no timing to speak of, the upstream and downstream
links are completely independent, and within one direction only one wire changes
at a time.

There are two things you need to set up for the links: the routing, and the links
themselves.

For the routing, you set system switch registers 0c and 0d to set the direction
for every address bit, for this switch; and registers 20..27 to set which external
link has which direction. An example, which assumes everything starts out as
having direction 0, and sets external link #2 ("A") as direction 1; bit 8000 goes
to direction 0, bit 4000 goes to direction 1:

Code: Select all

        u32 id = get_core_id();

        write_sswitch_reg(id, 0x0d, 0x01000000);
        write_sswitch_reg(id, 0x20+2, 1 << 8);
You need to set up routing on every sswitch.

To set up the links themselves, each sswitch handles its own outgoing link.
You set up the link speed (for the outgoing; the switch can handle whatever
speed incoming you throw at it, as long as the signal integrity is good).
You reset the incoming side of your link, to get a clean state. And you send
a HELLO control token, to tell the other side you have no credits and you
want some. The other side receives that and gives you some credits; you
see you have credits now, so that you can use the outgoing side. Example
(which does all this rolled into one function):

Code: Select all

static void init_2w_link_half(u32 n, u32 bittime)
{
        u32 id = get_core_id();
        bittime--;

        for (;;) {
                u32 x;

                write_sswitch_reg(id, 0x80 + n, 0x81800000 + 0x1001*bittime);
                udelay(1000);
                read_sswitch_reg(id, 0x80 + n, &x);
                if (x & 0x02000000)
                        break;
        }
}

...

        init_2w_link_half(2, 16);       // 400MHz/16 = 25MHz
        printf("Link up one way.\n");
The other side needs to set up its own outgoing link; or you can do that
from this core, because now you can send to the remote sswitch. To
detect if your link is initialised both ways, and everything is ready for
action:

Code: Select all

                read_sswitch_reg(id, 0x80 + n, &x);
                if ((x & 0x06000000) == 0x06000000)
                        ...; // all okay now!
Hope this helps,


Segher
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Hi,

Sorry to bother you, but your code looks a little like what I need to initialize my own boards. I have 2 XK-1A's attached to each other. They are preprogrammed at different times, so I need to negotiate the xlink after the compile of the code. I am really struggling here...

I am using a 2 wire connection between X0LD and X1LC (on the respective boards). I've beat my head bloody over this for the past three days. I saw the code and wiki on negotiating xlink connections. Attached is some code I am trying to get running. I can't seem to flash it. I get the following error:

"xrun: First stage multi-node boot failed, please check XN file and Xmos link connectivity"

Any clues on how I can move forward? I'm not looking for hot linking, I just don't have the processors hooked together in a JTag chain presently...

Slave XK-1A code

Code: Select all

#include <xs1.h>
#include <print.h>
#include <platform.h>

port leds0 = PORT_LED_1;

void flashLEDSlave  ( port leds, streaming chanend c )
{
    long a ;
    while (1)
    {
        c :> a ;
        leds <: a ;
    }
}

int main(void)
{
    streaming chan c ;
    par
    {
        on stdcore[0]: flashLEDSlave(leds0,c);
        waffleBakerOut(c) ;
    }
    return 0 ;
}

Slave XK-1A XN file

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
  <Type>Board</Type>
  <Name>XK-1A Development Board</Name>
  <BoardId>0005021X</BoardId>

  <Declarations>
    <Declaration>tileref tile[1]</Declaration>
  </Declarations>

  <Packages>
    <Package id="P1" Type="XS1-L1A-TQ128">
      <Nodes>
      
        <Node Id="Slave" InPackageId="0" Type="XS1-L1A" Oscillator="20MHz" SystemFrequency="400MHz" ReferenceFrequency="100MHz">
          <Boot>
            <Source Location="SPI:bootFlash1"/>
          </Boot>
          <Tile Number="0" Reference="tile[0]">
            <Port Location="XS1_PORT_1M" Name="PORT_SPI_MISO1"/>
            <Port Location="XS1_PORT_1N" Name="PORT_SPI_SS1"/>
            <Port Location="XS1_PORT_1O" Name="PORT_SPI_CLK1"/>
            <Port Location="XS1_PORT_1P" Name="PORT_SPI_MOSI1"/>
            <Port Location="XS1_PORT_4F" Name="PORT_LED_1"/>
          </Tile>
        </Node>
        
        <Node Id="1" Type="device:waffle_iron">
	      <Service Id="0" Proto="waffleBakerOut(streaming chanend cOut)">
	         <Chanend identifier="cOut" end="0:1:7" remote="0:0:6">
	         </Chanend>
	      </Service>
	    </Node>      
	     
	  </Nodes>
    </Package>
  </Packages>

  <Links>
    <Link Encoding="2wire" Delays="0,1">
      <LinkEndpoint NodeId="Slave" Link="X0LC"/>
      <LinkEndpoint NodeId="1" Link="X1LD"/>
    </Link>
  </Links>

  <ExternalDevices>
    <Device NodeId="Slave" Tile="0" Class="SPIFlash" Name="bootFlash1" Type="AT25FS010">
      <Attribute Name="PORT_SPI_MISO" Value="PORT_SPI_MISO1"/>
      <Attribute Name="PORT_SPI_SS"   Value="PORT_SPI_SS1"/>
      <Attribute Name="PORT_SPI_CLK"  Value="PORT_SPI_CLK1"/>
      <Attribute Name="PORT_SPI_MOSI" Value="PORT_SPI_MOSI1"/>
    </Device>
  </ExternalDevices>

  <JTAGChain>
     <JTAGDevice NodeId="Slave"  Position="0"/>
  </JTAGChain>

</Network>
Master XK-1A code

Code: Select all

#include <xs1.h>
#include <print.h>
#include <platform.h>

port leds0 = PORT_LED_0;


void Wait(unsigned int time)
{
    timer DelayTimer;
    int t;

    DelayTimer :> t;
    DelayTimer when timerafter(t + time) :> void;
}

void flashLEDMaster ( port leds, streaming chanend cOut )
{
    timer DelayTimer;
    long  t, a ;
    a = 0 ;
    DelayTimer :> t;
    while(1)
    {
        cOut <: a ;
        a++ ;
        leds <: a ;
        t += 12500000;
        DelayTimer when timerafter(t) :> void;
    }
}

int main(void)
{
    streaming chan c ;
    par
    {
        on stdcore[0]: flashLEDMaster(leds0,c);
        waffleBakerOut(c) ;
    }
	return 0 ;
}
Master XK-1A XN file

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
  <Type>Board</Type>
  <Name>XK-1A Development Board</Name>
  <BoardId>0005021X</BoardId>

  <Declarations>
    <Declaration>tileref tile[1]</Declaration>
  </Declarations>

  <Packages>
    <Package id="P0" Type="XS1-L1A-TQ128">
      <Nodes>
      
        <Node Id="Master" InPackageId="0" Type="XS1-L1A" Oscillator="20MHz" SystemFrequency="400MHz" ReferenceFrequency="100MHz">
          <Boot>
            <Source Location="SPI:bootFlash0"/>
          </Boot>
          <Tile Number="0" Reference="tile[0]">
            <Port Location="XS1_PORT_1M" Name="PORT_SPI_MISO0"/>
            <Port Location="XS1_PORT_1N" Name="PORT_SPI_SS0"/>
            <Port Location="XS1_PORT_1O" Name="PORT_SPI_CLK0"/>
            <Port Location="XS1_PORT_1P" Name="PORT_SPI_MOSI0"/>
            <Port Location="XS1_PORT_4F" Name="PORT_LED_0"/>
          </Tile>
        </Node>
        
        <Node Id="1" Type="device:waffle_iron">
	      <Service Id="0" Proto="waffleBakerOut(streaming chanend cOut)">
	         <Chanend identifier="cOut" end="0:0:6" remote="0:1:7">
	         </Chanend>
	      </Service>
	    </Node>      
	    
      </Nodes>
    </Package>
  </Packages>

  <Links>
    <Link Encoding="2wire" Delays="1,1">
      <LinkEndpoint NodeId="Master" Link="X0LD"/>
      <LinkEndpoint NodeId="1" Link="X1LC"/>
    </Link>
  </Links>

  <ExternalDevices>
    <Device NodeId="Master" Tile="0" Class="SPIFlash" Name="bootFlash0" Type="AT25FS010">
      <Attribute Name="PORT_SPI_MISO" Value="PORT_SPI_MISO0"/>
      <Attribute Name="PORT_SPI_SS"   Value="PORT_SPI_SS0"/>
      <Attribute Name="PORT_SPI_CLK"  Value="PORT_SPI_CLK0"/>
      <Attribute Name="PORT_SPI_MOSI" Value="PORT_SPI_MOSI0"/>
    </Device>
  </ExternalDevices>

  <JTAGChain>
     <JTAGDevice NodeId="Master" Position="0"/>
  </JTAGChain>

</Network>
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

By the way, I did try Flags="noinit" in the link section. But then, I get some errors thrown because the links are not properly routed underneath.

Thanks,
GJN
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Step -4: Decide the architecture: are both nodes already
running, or do you boot one over this link? Does the slave
participate in the link init? Etc.
Step -3: Hook up a logic analyser.
Step -2: Make sure your code runs at all.
Step -1: Arrange some way to get register dumps (of the
sswitch) out; printf will do.
Step 0: Make sure nothing is trying to send anything on
the links you are trying to set up.

Now that you have a sane environment for debugging, you
can start writing the code to initialise the links. First node
id, then routing table, then master tx, then slave tx.
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Segher,

Thanks so much for replying. Yeah, I'm trying to get a sane debugging environment. Trouble is I cannot debug the first stage boot loader (which initializes the links). That is completely done by the compiler. I can see the code in the xobjdump, but that's it.

I really need a sort of hot-plug setup as described in this thread that DrNO was working on and that you helped him with...I have some code I generated that mimics what you spelled out earlier (see attached files and below code). I manually set up the switches, but after that, I don't know what to do. The documentation is a little fuzzy when it describes the link directions bits. What I really need to know is how to attach the channel to the switch properly. Optimally, I'd like to use static forwarding to simplify things. I simply want to go from X0LD on the L1-128 to X0LC on the SU1. 2 wire for testing using the XK-1A's, 5 wire for the board I have made.

Here is some of the code I have:

Code: Select all

#include <xs1.h>
#include <print.h>
#include <platform.h>

port leds0 = PORT_LED_1;

void flashLEDSlave  ( port leds, streaming chanend c )
{
    unsigned x, retries, ncnt;
    unsigned id = get_local_tile_id();
    long strch ;

    ncnt = 0 ;

    // First, reset all the links
    for (x=0; x<8; x++)
        write_sswitch_reg(id, 0x80+x, 0x00000000) ;
    // Set the core id to 0 for the slave
    write_sswitch_reg_no_ack(id, 0x05, 0x00000000) ;

    do
    {
        // Set our direction switch to 0 for the slave
        write_sswitch_reg(0, 0x20, 0x00000000) ;
        // Enable node with no hello.  Bit flags set:
        // 31 - Enable link
        // 23 - Reset input state machine
        // 11 - At least 1 clock intra symbol timing
        write_sswitch_reg(0, 0x80, 0x80800000) ;
        // Set direction bits for slave
        write_sswitch_reg(0, 0x0c, 0x11111110);
        write_sswitch_reg(0, 0x0d, 0x11111111);
        // Reset as seen in prologue of XMOS code
        write_sswitch_reg(0, 0x80, 0x81800800);
        leds <: (0x01 + ((ncnt>>12)<<2));
        ncnt++;
        // The following sets up the initial link between nodes...
        retries=250;
        while(retries--)
        {
             read_sswitch_reg(0, 0x80, x);
             if (x & 0x04000000)
                 break;
        }
    } while ((x&0x04000000)==0) ;
    leds <: 0x0d ;

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // What do I do to attach it to the channel?  Can I then
    // use the channel for c<:a; and c:>a style input and output?

    while(1);
}

int main(void)
{
    streaming chan c ;
    flashLEDSlave(leds0,c);
    return 0 ;
}
1. Architecture: In the end I will have an SU1-FB96 attached to an L1-128. The L1-128 needs to be completely powered down for most of it's existence, so this really ends up being a hot-plug sort of arrangement. SU1 has it's XLC 5 wire attached to the L1-128 XLD 5 wire. The boards have already been spun. The SU1 also controls the core 1.0v voltage converter enable as well as the 3.3v I/O voltage converter enable pin. I am simulating it by using two XK-1A's. Just trying to get the software doing a simple test transfer in one direction, from the L1-128 to the SU1-FB96. I simulate the power down situation by simply not attaching the other XK-1A board. (The JTag lines are separate too...)

2. I have an OScope (Tektronix TDS 2024C 200MHz 2GS/s 4Ch Color). It's not really necessary. I know the code is crashing when trying to go through it's initialization of the switches (the first loadable code from the EEPROM). I don't think it's that deep of a problem. I think I just can't do it as I described below, I need to use what you were helping DrNO with.

The documentation isn't that straight forward on how to do all of this. Thank you for your patience!
You do not have the required permissions to view the files attached to this post.
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Segher,

Did I say thank you? Thanks again!

I forgot to add, that I am fairly comfortable with assembly language in XMos. It's just this networking stuff that's giving me the pain.

I know I will need to take the provided channel ends and somehow use the SETD command to give it the destination channel end. For the static forwarding, I need to set 0xA0-0xA7 (depending on the link desired) and set the destination cored id and the destination channel end (i think it's the destination). I do not know the rhyme or reason of the link dir bits in the 0x20-27 registers either.

So. Sorry to dump on you...

GJN
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

So your slave (the L in the final product) boots by itself,
from SPI or similar?

You need to set the link speed to something slower than
the few hundred MHz you do now. 1MHz is nice for bringup.
Use the LA (or scope or whatever you have handy) to see
if any signal is getting out, what speed, and then decode it,
see if it is the expected HELLOs etc. 2w links are simpler
to decode (and probe).

You probably do not want to use static forwarding. Normal
routed messages are more flexible and work much better
together with other code.

And do dump the sswitch registers at strategic places in
your init sequence, you want to know what is going on!
First dump it before you did anything, so you get to see
what state everything is in after the bootloader did its
thing.