Using read_sswitch_reg() over a link

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
Hooligan
Member++
Posts: 16
Joined: Mon May 02, 2011 12:39 pm

Using read_sswitch_reg() over a link

Post by Hooligan »

I have two XS1-L devices connected by a two bit link. Link speed, timing and width match and I am able to exchange HELLO messages between the devices. Routing IDs, and links are set up properly but I am getting no response when trying to read registers in the remote switch using read_sswitch_reg().

The remote device is in boot mode from the ROM and I can feed it an image over the link which the remote receives and runs just fine (albeit at the wrong clock rate.) It seems like everything is set up correctly but the read hangs forever. Before I resort to assembler and start poking tokens down the link, would anyone have a thought as to what might be wrong?


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

Post by segher »

It is not clear what you mean with "set up properly": if that was true, it would
all just work ;-) You don't give many details, so I'll just guess.

I'll name the two nodes "local" and "remote".

You can send a boot image over the link, so presumably you have set the node
of the remote node (and local if needed) [reg 0x05]. Also the link from local
to remote is up.

The boot code (in ROM, which you run on the remote node) does not send a
HELLO, so the remote -> local half-link has no credits. You should write the
remote phys link register to make it say HELLO [reg 0x83].

You also need to set up routing correctly on the remote node (and the local
node). For a two-node system that is rather easy, there is only one link,
so you can have all directions the same, which they are by default [reg 0x0c and
0x0d]. Direction per link [reg 0x23] won't need changing either.

One last thing though: the boot code enables more than just link B, it enables
all four internal links (on an L2) as well. You should disable those [reg 0x84
to reg 0x87] or it might route your replies to those links, and those aren't up,
so you probably want to avoid that.
User avatar
Hooligan
Member++
Posts: 16
Joined: Mon May 02, 2011 12:39 pm

Post by Hooligan »

segher wrote:It is not clear what you mean with "set up properly": if that was true, it would
all just work ;-)
Exactly! It seems that it should "just work." Sorry for the lack of detail in my post. I was called away for an emergency in the middle of composing.
  • Here's the setup:
  • Master L2 - core 0 booting from XTAG-2 with XSYS, core 1 with 2 bit link on X1LB
    Core 0 routing ID 0xC000, Core 1 routing ID 0xE000
    X1LB belongs to direction 1, all other links are direction 0 (towards core 0)
    The master has an I/O line driving the reset on the slave.
  • Slave L2 - core 0 boots from link X0LB, core 1 boots from internal links.
    Routing IDs are 0x0000 for both cores
I can boot an image on core 0 of the slave per the steps in the XS1-L System Spec.
  • On the master:
  • Enable X1LB in two bit mode and set speed, timing and width appropriately
  • Reset the link
  • Send HELLO and wait for credits from the slave
  • Issue credit to the slave in response to its HELLO
  • Configure routing for X1LB
  • Allocate a channel end and configure it for core ID 0
  • Send the allocated channel end to the slave
  • Send size, code, and CRC
  • Send END token, get END token
  • Free the channel end
This all works fine. Unfortunately, I need to set up the slave's PLL before sending the image. It seems that read_sswitch_reg() and write_sswitch_reg() are designed for this task. Since these don't take a channel end as a parameter it implies that they handle the allocation and configuration of the channel internally.

I suppose it's possible that these functions are not capable of accessing a switch on another node. If that's the case, I'll have to crank out replacements based on section 3.5 of the System Spec. That's not that hard but it bugs me to be stumped by something that appears to be so simple.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

This all works fine. Unfortunately, I need to set up the slave's PLL before sending the image. It seems that read_sswitch_reg() and write_sswitch_reg() are designed for this task. Since these don't take a channel end as a parameter it implies that they handle the allocation and configuration of the channel internally.
Yes.
I suppose it's possible that these functions are not capable of accessing a switch on another node. If that's the case, I'll have to crank out replacements based on section 3.5 of the System Spec. That's not that hard but it bugs me to be stumped by something that appears to be so simple.
They can access another core just fine.

You cannot receive answers from the slave until you have set up everything on
the slave properly, so you cannot read the switch regs. Using write_sswitch_reg()
isn't going to work either as long as the path back doesn't work (it does a CHKCT
for the expected END token).

While debugging / bringing up this code, you should read the sswitch regs via
JTAG, it is rather hard to do this blindly...
User avatar
Hooligan
Member++
Posts: 16
Joined: Mon May 02, 2011 12:39 pm

Post by Hooligan »

Well segher, you had it right. I wrote a little program for the slave to set up the links and routing. After loading that to the slave I could happily read and write registers at will.

As a quick experiment, I tried writing a bit of code for the master that writes to the registers on the slave but does not look for any return traffic. Using that I can set up the links and routes properly on the slave and then read and write the registers as expected.

Thanks for pointing me in the right direction.
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Hi...

Trying to set up a test application using two XK-1A's. I want to use a "service" to represent the link I will later try to initialize in code. I do NOT want to have the SPI's programmed as a multi-tile boot. I want to program each SPI separately and then connect the XK-1A's later. (There is a method to my madness, and no, I do not make hats).

I used the noinit flag mentioned in this post thread to get my code to run up to the point it actually tries to access the "service" channel. Both the master and the slave correctly compile and run, and on the first attempt to either read or write to the "service" channel, an ET_ILLEGAL_RESOURCE exception (correctly) gets thrown. WHAT I NEED IS A SEQUENCE OF CALLS IN XC TO SAY "HELLO" TO THE L1 THAT WILL LATER BE CONNECTED, AND WAIT FOR A VALID CONNECTION OF THE LINKS. Since I am using the XK-1A's they are X0LC(slave) and X0LD(master). Whatever code is used should properly set up these channels. Can someone help me fill in the "BLANKS"? I know it will need some read_sswitch_reg and write_sswitch_reg calls, but I couldn't quite divine it from this forum's posts...

My end product is combining several camera streams (up to 4) on an L1-128QFP and sending it to an SU1 and then to the USB 2.0 line. That application will have a 5 wire link, the L1-128 using X0LD, and the SU1 using X0LC. I already have the board printed and will assemble it, but I am trying to get my code ready this weekend...



Here is my slave code:

Code: Select all

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

port leds0 = PORT_LED_1;

long nMillionSlave = 4000000 ;

void flashLEDSlave(port leds, streaming chanend c)
{
    long a ;
    long i ;

    // We need to initialize the link before attempting to read.
    // We will do this by using read_sswitch_reg and write_sswitch_reg
    printstr("Hello!  Entering flashLEDSlave\n");

    // Do some initialization of the links here:
    //    HELP ME HERE!  I NEED SOME READ_SSWITCH_REG AND WRITE_SSWITCH_REG
    //    CALLS HERE
    //    BLANKS

    // Check that the link really works...
    printstr("Try to read first byte\n");
    c :> a ;

    printstr("O.K. That's done\n");
    while(1)
    {
        // Loop and calculate the
        for (i=0; i<4000000; i++)
            c :> a ;
        c :> a ;
        c :> a ;
        leds <: a ;
    }
}

int main(void)
{
    streaming chan c ;
    par
    {
        //flashLEDSlave(leds0, c);
        on stdcore[0]: flashLEDSlave(leds0, c);
        waffleBaker(c) ;
    }
	return 0 ;
}
Here's my slave 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="waffleBaker(streaming chanend cIn )">
	         <Chanend identifier="cIn" end="0:0:6" remote="0:1:0"/>
	      </Service>
	    </Node>
	    
      </Nodes>
    </Package>
  </Packages>

  <Links>
  <Link Encoding="2wire" Delays="0,1" Flags="noinit">
  <LinkEndpoint NodeId="Slave" Link="X0LC"/>
  <LinkEndpoint NodeId="1" Link="X0LD"/>
  </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>
Here is my master code:

Code: Select all

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

port leds0 = PORT_LED_0;

long nMillionMaster = 4000000 ;

void flashLEDMaster(port leds, streaming chanend c)
{
    long            a ;
    long            i ;

    // We need to initialize the link before attempting to read.
    // We will do this by using read_sswitch_reg and write_sswitch_reg
    printstr("Hello!  Entering flashLEDMaster\n");

    // Do some initialization of the links here:
    //    HELP ME HERE!  I NEED SOME READ_SSWITCH_REG AND WRITE_SSWITCH_REG
    //    CALLS HERE.  DON'T START SENDING UNTIL WE HAVE A VALID LINK.
    //    BLANKS

    // Check that the link really works...
    printstr("Try to write first byte\n");
    c <: a ;

    printstr("O.K. That's done\n");

    while(1)
    {
        a = 1 ;

        for (i=0; i<4000000; i++)
            c <: i ;
        c <: 1 ;
        leds <: a ;

        a = 0 ;
        for (i=0; i<4000000; i++)
            c <: i ;
        c <: 0 ;
        leds <: a ;
    }
}

int main(void)
{
    streaming chan c ;
    par
    {
        on stdcore[0]: flashLEDMaster(leds0, c);
        waffleBaker(c) ;
    }
	return 0 ;
}
Here is my master XN:

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="waffleBaker(streaming chanend cIn )">
	         <Chanend identifier="cIn" end="0:0:6" remote="0:1:0"/>
	      </Service>
	    </Node>

      </Nodes>
    </Package>
  </Packages>

  <Links>
  <Link Encoding="2wire" Delays="0,1" Flags="noinit">
  <LinkEndpoint NodeId="Master" Link="X0LD"/>
  <LinkEndpoint NodeId="1" Link="X0LC"/>
  </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>