Question about xcore SPI implementation

New to XMOS and XCore? Get started here.
aubreyrjones
New User
Posts: 3
Joined: Mon Jan 07, 2013 9:05 pm

Question about xcore SPI implementation

Postby aubreyrjones » Fri Feb 08, 2013 8:38 pm

I'm implementing an interface to a not-quite-SPI chip. Since there's no MISO line in the interface, I didn't want to use the standard SPI module as it requires all four ports. But, I've been looking at the 'sc_spi' implementation as reference.

In spi_master.xc::spi_master_out_byte_internal(), there's the following code:

Code: Select all

// handle first bit
asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
spi_if.mosi <: x; // output first bit
asm("setc res[%0], 8" :: "r"(spi_if.mosi)); // reset port
asm("setc res[%0], 0x200f" :: "r"(spi_if.mosi)); // set to buffering
asm("settw res[%0], %1" :: "r"(spi_if.mosi), "r"(32)); // set transfer width to 32
stop_clock(spi_if.blk2);
configure_clock_src(spi_if.blk2, spi_if.sclk);
configure_out_port(spi_if.mosi, spi_if.blk2, x);
start_clock(spi_if.blk2);
The purpose of this code is fairly clear: driving the low-bit value before the clock to accomodate CPHA=0. This requires unbuffering the port, then resetting the buffering options to return to normal operation.

But, what confuses me is the line

Code: Select all

asm("settw res[%0], %1" :: "r"(spi_if.mosi), "r"(32)); // set transfer width to 32
That line appears to set the buffering width of a single-bit port to 32 bits. But, if I try to do "buffered out port:32 if_mosi = XS1_PORT_1E;", the XC compiler tells me that I'm only allowed to buffer 8 bits on a 1-bit port. I assume this isn't an error in the SPI code. But, what explains the discrepancy between the settw instruction buffering 32 bits, and the XC declaration that won't take more than 8 bits? What does the settw actually accomplish in this situation?
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Postby richard » Sat Feb 09, 2013 2:46 pm

That line appears to set the buffering width of a single-bit port to 32 bits. But, if I try to do "buffered out port:32 if_mosi = XS1_PORT_1E;", the XC compiler tells me that I'm only allowed to buffer 8 bits on a 1-bit port. I assume this isn't an error in the SPI code. But, what explains the discrepancy between the settw instruction buffering 32 bits, and the XC declaration that won't take more than 8 bits? What does the settw actually accomplish in this situation?
You should be able to use a transfer width of 32 with a 1-bit port in XC. The following example compiles fine for me:

Code: Select all

#include <xs1.h>

buffered out port:32 p = XS1_PORT_1E;

int main() {
  p <: 0;
  return 0;
}
What error do you get?
aubreyrjones
New User
Posts: 3
Joined: Mon Jan 07, 2013 9:05 pm

Postby aubreyrjones » Sat Feb 09, 2013 7:37 pm

It was my mistake, actually.

I had, earlier in hacking around on this, tried to set the transfer with of a port to 16 bits (not 32). That complained, saying that a width of 16 isn't supported on a 1-bit port.

My mistake was that I assumed that the problem was transfer width > 8, not that only specific widths were supported. Of course when I tried 'port:32' it worked fine.

Still, why does the assembly code set the TW to 32, when the declaration of the SPI interface struct has it 8-bits buffered?
User avatar
xsamc
Active Member
Posts: 55
Joined: Fri Mar 04, 2011 3:38 pm

Postby xsamc » Mon Feb 11, 2013 12:31 pm

aubreyrjones wrote:Still, why does the assembly code set the TW to 32, when the declaration of the SPI interface struct has it 8-bits buffered?
It looks like it could well be a bug to me, and that the transfer width should be being set to 8 in spi_master_out_byte_internal(). I suspect that as spi_master_out_byte_internal() has to reset the port at the start of each output, the transfer width being wider than it should is not causing an issue.

I'll double check this and update the component as required, when I get a chance to test it properly :)

Who is online

Users browsing this forum: No registered users and 5 guests