"service" functions in XC. How to?

Technical questions regarding the XTC tools and programming with XMOS.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

I was looking for a platform.h

The only one I can find is DesktopTools/9.9.2/target/include/platform.h

which only reads:

Code: Select all

#ifndef _platform_h_
#define _platform_h_
#ifdef _PLATFORM_INCLUDE_FILE
#include _PLATFORM_INCLUDE_FILE
#else
extern core stdcore[];
#endif /* PLATFORM_INCLUDE_FILE */
#endif /* _platform_h_ */
As I don't know what _PLATFORM_INCLUDE_FILE is defined as I'm a bit lost trying to find the actual auto-generated stuff. Is it deleted after compilation?


User avatar
trousers
Active Member
Posts: 44
Joined: Fri Dec 11, 2009 10:20 am

Post by trousers »

Heater wrote:I was looking for a platform.h
As I don't know what _PLATFORM_INCLUDE_FILE is defined as I'm a bit lost trying to find the actual auto-generated stuff. Is it deleted after compilation?
Yes it is.

In 9.9.2 you can generate it manually using xnc. The xnc binary lives where the environment variable XCC_EXEC_PREFIX points. Running it with "-H <xnfile>" will produce a file with a ".h" suffix instead of ".xn" and that is what ends up as "platform.h".

That said, xnc is not a supported tool; it may not be there in the next release, for example.
Best friends with the code fairy.
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

OK Thanks. So it does.
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"?

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>
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

You will need to:
  • Configure the direction of the link to ensure packets take the correct route across the network.
  • Enable the link and establish credit in both directions so that packets can be sent across the link.
If you leave the configuration of the network to the tools then you won't know what direction to use for the link. Therefore you should manually specify the network setup in your .xn files as described here:

https://www.xmos.com/support/documentat ... nent=17556

You can then use the following code to setup the link on both sides (warning: untested):

Code: Select all

#include <xs1.h>

void configure_link(tileref tile, unsigned linkNum, unsigned direction,
                    int isFiveWire, unsigned intraTokenDelay,
                    unsigned interTokenDelay)
{
  assert(intraTokenDelay > 0 && interTokenDelay > 1);
  unsigned regVal;

  // Setup link direction.
  regVal = 0;
  regVal = XS1_LINK_DIRECTION_SET(regVal, direction);
  write_node_config_reg(tile, XS1_SSWITCH_SLINK_0_NUM + linkNum, regVal);

  // Say hello.
  regVal = 0;
  regVal = XS1_XLINK_INTRA_TOKEN_DELAY_SET(regVal, intraTokenDelay - 1);
  regVal = XS1_XLINK_INTER_TOKEN_DELAY_SET(regVal, interTokenDelay - 2);
  regVal = XS1_XLINK_WIDE_SET(regVal, isFiveWire);
  regVal = XS1_XLINK_ENABLE_SET(regVal, 1);
  regVal = XS1_XLINK_HELLO_SET(regVal, 1);
  write_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, regVal);

  // Wait for someone to say hello to us.
  unsigned tmp;
  do {
    read_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, tmp);
  } while (!XS1_RX_CREDIT(tmp));

  // Say hello again.
  write_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, regVal);
}
The link numbers are as follows:
XLC - 0
XLD - 1
XLB - 2
XLA - 3
XLG - 4
XLH - 5
XLE - 6
XLF - 7
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Richard,

Thanks! I am getting ready to test now.

Question, in the services declaration of the XN file, how should I specify the channel end information for the service? I am sure this will have an impact.

Will the following work? Or is it unnecessary?

Right now, both my master has the following node to specify the service

Code: Select all

<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:7"/>
  </Service>
</Node>
and my slave has the following node to specify its service:

Code: Select all

<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"/>
  </Service>
</Node>
Thanks again for any information you can give!
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Richard,

It failed. Here is my code and xn file just for the slave part of the code. I was hoping that it would get to the configure_link function, but it crashes in the main function well before it hits any of the code I wrote. Do you have an XK-1A lying around?

The idea is that I should be able to run the code on a single XK-1A and have it hang in the configure_link function until another XK-1A gets attached to the XSYS connector. Then, the link should be established.

By the way. All of this stuff is quite undocumented and confusing. I've blown a week trying to figure it out. I hope my description of the problem isn't too confusing either.

Slave XC code

Code: Select all

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

port leds0 = PORT_LED_1;

#define XLC 0
#define XLD 1
#define XLB 2
#define XLA 3

void configure_link(tileref tile, unsigned linkNum, unsigned direction,
                    int isFiveWire, unsigned intraTokenDelay,
                    unsigned interTokenDelay,port leds)
{
    unsigned regVal;
    //assert(intraTokenDelay > 0 && interTokenDelay > 1);

    leds <: 1 ;
    // Setup link direction.
    regVal = 0;
    regVal = XS1_LINK_DIRECTION_SET(regVal, direction);
    write_node_config_reg(tile, XS1_SSWITCH_SLINK_0_NUM + linkNum, regVal);

    leds <: 2 ;
    // Say hello.
    regVal = 0;
    regVal = XS1_XLINK_INTRA_TOKEN_DELAY_SET(regVal, intraTokenDelay - 1);
    regVal = XS1_XLINK_INTER_TOKEN_DELAY_SET(regVal, interTokenDelay - 2);
    regVal = XS1_XLINK_WIDE_SET(regVal, isFiveWire);
    regVal = XS1_XLINK_ENABLE_SET(regVal, 1);
    regVal = XS1_XLINK_HELLO_SET(regVal, 1);
    write_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, regVal);

    leds <: 3 ;
    // Wait for someone to say hello to us.
    unsigned tmp;
    do
    {
        read_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, tmp);
    } while (!XS1_RX_CREDIT(tmp));

    leds <: 4 ;
    // Say hello again.
    write_node_config_reg(tile, XS1_SSWITCH_XLINK_0_NUM + linkNum, regVal);
}

void flashLEDSlave  ( port leds, streaming chanend c )
{
    long a ;
    configure_link ( tile[0]
                   , XLC        // Use link c
                   , 1          // Direction = 1
                   , 0          // 2 wire
                   , 1          // Intertoken delay
                   , 2          // Intratoken delay
                   , leds ) ;
    leds <: 0xf;
    while (1)
    {
        c :> a ;
        leds <: a ;
    }
}

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

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" ManuallySpecifiedRouting="true">
  <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" RoutingId="0">
          <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>
          <RoutingTable>
            <Bits>
              <Bit number="0" direction="1"/>
            </Bits>
            <Links>
              <Link name="XLB" direction="1"/>
            </Links>
          </RoutingTable>
        </Node>
      </Nodes>
    </Package>
  </Packages>
  <Links>
    <Link Encoding="2wire" Delays="0,1">
      <LinkEndpoint NodeId="Slave" Link="XLB"/>
      <LinkEndpoint NodeId="1" Link="XLB"/>
    </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>

  <Nodes>
    <Node Id="1" Type="device:waffle_iron" RoutingId="1">
      <Service Id="0" Proto="waffleBakerOut(streaming chanend cOut)">
        <Chanend identifier="cOut"/>
      </Service>
    </Node>
  </Nodes>  
    
  <JTAGChain>
    <JTAGDevice NodeId="Slave" Position="0"/>
  </JTAGChain>
</Network>
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Richard,

By the way, here is some working code that gets me to the point where the switches are talking to each other (saying hello on both sides). It correctly waits until both boards are attached to each other. It is very similar to what you gave me in your post. Just more verbose, and I am setting the tile id to a different value on entry. I don't declare any links in the XN file so that I don't crash.

The sections of code in question are in the function flashLEDSlave and flashLEDMaster. I have a sneaking suspicion that it's the settings for the channels and the direction bits (registers 0xC and 0xD being set by write_sswitch_reg) that are hammering me. I can never get my code past the link up point. No passing of data occurs at the bottom of the functions.

I am simply stuck at how to get the channels set up correctly so they can start talking. Really, at this point, any solution that allows me to do this hot plug is acceptable. My project is at a standstill until I solve this, and I really want to use XMOS in this project.
You do not have the required permissions to view the files attached to this post.
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

I noticed the following in your source code:

Code: Select all

SetN(c,0x00040002);
You shouldn't need to change the network of the channel end. Networks are used to partition the network into multiple virtual networks so you can control which traffic goes over which links (e.g. for QOS guarantees). Unless you have a specific need for this I would take out the call to SetN. If you change the network of a channel end without changing the networks of the links you won't be able to send or receive any data from other tiles.
GerhardNorkus
Active Member
Posts: 55
Joined: Wed Jan 05, 2011 2:15 pm

Post by GerhardNorkus »

Hi Richard,

I removed the set network calls. Still no success.

Any idea as to why the manually specified route crashes on initial running of the program?

Thx