SPI on P32A

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
User avatar
GeorgeIoak
Active Member
Posts: 56
Joined: Wed May 19, 2010 9:42 pm

SPI on P32A

Post by GeorgeIoak »

Hello and Happy New Year Everyone!

I don't have much experience yet with programming the L1 device and didn't see much information about doing this. I want to use SPI on the P32A port (XOD55, 56, 57) and the port is currently being used with some other functions. Fortunately the 5 other pins defined are all output pins and I only need to be a master and send data so I think that helps by configuring the port as an output only.

The examples I found are using single bit ports for SPI so hopefully somebody has some helpful advice or code examples for me to study.

Thanks!
George


User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm
Contact:

Post by Berni »

Well you have to bitbang spi in software just like you would on I/O pins of any other micro. What usually makes the situation a lot worse is if you already use the port for something, since that means you have to implement your SPI code inside the thread thats already using the port(You cant use one port from multiple threads) Also since you can only write the port as a whole you have to make sure you write the same value to the bits that are used for the other functions (If you read from it it will turn the port to a input or generate a compiler error).
User avatar
GeorgeIoak
Active Member
Posts: 56
Joined: Wed May 19, 2010 9:42 pm

Post by GeorgeIoak »

OK, so I found port32A.S from the USB Audio Reference Design and how they use port32A_peek and port32A_out. Are there any code snippets for SPI using those functions are should I just create my own?
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

I do not remember who I discussed it earlier, but it is also the possibility to use the already existing SPI on the L1 which communicates with the flash. Use a pull up (or pull down) on Chip Select to deactivate the other chips during boot-up. Thereafter you can use the P32A as an output only to activate the other SPIs with the CS. Probably much easier.

Correct me if that wouldn't work for some reason.
Probably not the most confused programmer anymore on the XCORE forum.
User avatar
GeorgeIoak
Active Member
Posts: 56
Joined: Wed May 19, 2010 9:42 pm

Post by GeorgeIoak »

Well that was my original intention but when I asked the question it was "recommended" to add onto the SPI bus. That was several months ago and maybe there was some misunderstanding but the damage is done at this point and my device is not wired onto the EEPROM SPI bus.

I worked a little on the code today and hacked together something that appears to work although it is far from elegant. It looks like I've got a glitch in the code when I call MyBang back to back with DATA=1, when I do this I get a short 0 pulse between the data.

Maybe you guys can see how I can clean this up:

Code: Select all

void MyBang (int cycle, int highlow)
{
	unsigned tmps;
	unsigned mytmp;
	unsigned portDat;

	tmps = port32A_peek();
	mytmp = tmps;
	portDat = tmps;
	if (highlow)
	{
		portDat |= P32A_SDIN;
	}
	else
	{
		portDat &= (~P32A_SDIN);
	}
	port32A_out(portDat);

	for (int i=0; i<cycle; i++)
	{
		Wait250us();
		port32A_out(portDat | P32A_SCK);
		Wait250us();
		mytmp = port32A_peek();
		mytmp &= (~P32A_SCK);
		port32A_out(mytmp);
		//Wait250us();
	}
	port32A_out(tmps);
}
and then in my main program I run this:

Code: Select all

    // Bit Bang SPI, Start CS High
    tmp = port32A_peek();
    tmp |= P32A_CS;
    port32A_out(tmp);

    MyBang(4,0); //Control Address[6:3]
    MyBang(2,1); //Control Address[2:1]
    MyBang(1,0); //Control Address[0]
    MyBang(1,0); //Control Data[8]
    MyBang(5,0); //Control Data[7:3]
    MyBang(1,1); //Control Data[2] FIRSEL
    MyBang(1,0); //Control Data[1]   "
    MyBang(1,1); //Control Data[0]   "

    // Toggle CS Low
    tmp = port32A_peek();
    tmp &= (~P32A_CS);
    port32A_out(tmp);
    Wait250us();
    tmp |= P32A_CS;
    port32A_out(tmp);
User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm
Contact:

Post by Berni »

If it helps you any this is the SPI code i used on a 4bit port. What it basically does is send the 8bit byte out the SPI and keeps CS in whatever state it is in the variable.

Code: Select all

void flash_SendSPI(unsigned char data)
{
	int i;
	unsigned char Bit = data >> 7;
	SPI <: (TmpCS + Bit);
	spi_delay;
	for (i = 0; i < 8; ++i)
	{
		Bit = data >> 7;
		SPI <: (TmpCS + Bit);
		spi_delay;

		SPI <: (TmpCS + Bit + Clk);
		spi_delay;
		data <<= 1;
	}
	spi_delay;
	SPI <: (TmpCS + Bit);
}
User avatar
GeorgeIoak
Active Member
Posts: 56
Joined: Wed May 19, 2010 9:42 pm

Post by GeorgeIoak »

Thanks Berni. Just for clarification I don't see the following variable defined in your snippet, TmpCS, SPI, and Clk. How do you have them defined?

I wanted to send a byte and shift it out like you did but it wasn't working for me so I switched to the more brain dead method! ;)
User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm
Contact:

Post by Berni »

Those are simply defined only containing the right bit set. So if its on pin 0 you put in 0x1 if its on pin 2 you use 0x4. Only the CS changes so it selects the right device and keeps it selected during all the bit wiggling.

SPI is the port since you see the <: channel output operations on it.

Oh and also note that this is SPI with a rising edge clock. If your SPI device is falling edge active you need to move the + Clk up
Post Reply