Buffered output clocked on an input clock (SPI MISO) Topic is solved

Technical discussions around xCORE processors (e.g. General Purpose (L/G), xCORE-USB, xCORE-Analog, xCORE-XA).
User avatar
mattb
Member
Posts: 13
Joined: Wed Aug 28, 2019 11:45 pm

Buffered output clocked on an input clock (SPI MISO)

Postby mattb » Wed Nov 13, 2019 12:52 am

Hello all,

I am trying to improve some bit-bashed SPI-slave code we have (where the XMOS responds to command from a host micro). We currently have it polling the SCLK line and then outputting the MISO bits as appropriate for the response coming from the XMOS back to the host. This ends up being a bit slow, and after researching, I thought I could use buffered and clocked IO to speed this up.

What I thought I could to do is attach a clock block whose source is the SCLK port to my output buffered MISO port. Then when I write the byte to the MISO port, it will clock out the 8 bits on the trailing edges of the incoming SCLK. Here's a very isolated program that I thought would work:

Code: Select all

#include <platform.h>
#include <xclib.h>

on tile[0] : port PORT_SCLK = PORT_TEST_SCLK; //1-bit port (XS1_PORT_1E)
on tile[0] : in buffered port:8 PORT_MOSI = PORT_TEST_MOSI; //1-bit port (XS1_PORT_1K)
on tile[0] : out buffered port:8 PORT_MISO = PORT_TEST_MISO; //1-bit port (XS1_PORT_1A)
on tile[0] : port PORT_NSS = PORT_TEST_NSS; //1-bit port (XS1_PORT_1P)

on tile[0] : clock CLOCK_SCLK = XS1_CLKBLK_1;

static unsigned char transmit_val = 0x00;

int main()
{
    par
    {
        on tile[0]:
        {
            unsigned char nSS_val;
            unsigned char MISO_val;

            set_clock_on(CLOCK_SCLK);
            configure_clock_src(CLOCK_SCLK, PORT_SCLK);
            configure_out_port(PORT_MISO, CLOCK_SCLK, 0);
            start_clock(CLOCK_SCLK);

            while (1)
            {
                //Wait for nSS to be active
                while (1)
                {
                    PORT_NSS :> nSS_val;
                    if (nSS_val == 0)
                    {
                        break;
                    }
                }

                //Now send out the transmit value on MISO when the SCLK happens
                MISO_val = bitrev(transmit_val) >> 24; //Bitswap to send MSb first
                clearbuf(PORT_MISO);
                PORT_MISO <: MISO_val;
                sync(PORT_MISO);

                //Increment our transmit value for next loop
                transmit_val++;
            }
        }
    }
    return 0;
}
So everytime the host sends a byte (I've hacked the host to just send a single byte on a button press), this code should increment the response back to the host (i.e 0x00, then 0x01, then 0x02, etc), and I should see that on the MISO line synched up with the SCLK edges.

Except, it is not working as expected. I do get something output on the MISO line, but the data seen seems fairly random, and not at all sequential. I also read there may be issue with things being shifted by 1-bit (i.e. MODE0/2 vs MODE1/3), but even taking that into account, it does not seem to jive.

Anything obvious that I'm doing wrong? I know there is the spi_lib from XMOS and that has a full SPI slave implementation, but it's pretty heavy weight for what I need to do, and I want to understand how these buffered IOs work before I commit to that or lift parts of it for my own.
View Solution
User avatar
mon2
XCore Legend
Posts: 1815
Joined: Thu Jun 10, 2010 11:43 am

Postby mon2 » Wed Nov 13, 2019 1:10 am

happy Tuesday mattb.

for conditional input port testing, you could further simplify to:

Remove:

Code: Select all

//Wait for nSS to be active
                while (1)
                {
                    PORT_NSS :> nSS_val;
                    if (nSS_val == 0)
                    {
                        break;
                    }
                }
and replace with:

Code: Select all

//Wait for nSS to be active
PORT_NSS when pinsneq ( 1 ) :> nSS_val; // this line should cause for PORT_NSS to be 0 before sampling and placing this value into nSS_val

Review and revise your buffered output port use as per attached (taken from XS1 Ports Specification).

xmos_buffered_out.png
Try again. Please post your results.
You do not have the required permissions to view the files attached to this post.
User avatar
mattb
Member
Posts: 13
Joined: Wed Aug 28, 2019 11:45 pm

Postby mattb » Thu Nov 14, 2019 12:46 am

Hey mon2,

Even looking at that app note, I was unable to get the clocked/buffered output to work properly.

However, after looking at you're suggestion on changing the wait for nSS, I applied that to my old bit-bashed code looking for SCLK changes and it sped it up considerably.

I am good to go for now. If I need to revisit later, at least I know my theory wasn't out to lunch, maybe just something in my implementation.

Thanks!

Who is online

Users browsing this forum: No registered users and 4 guests