Question about xcore SPI implementation

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

Question about xcore SPI implementation

Post by aubreyrjones »

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

Post by richard »

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

Post by aubreyrjones »

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

Post by xsamc »

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 :)
Post Reply