cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Voyager
Voyager
13,362 Views
Registered: ‎04-10-2012

Can someone spot my silly mistake in microblaze SPI code?

I have been struggling with a simple microblaze project on a custom board recently and I am sure it is more user errors on my part.  

 

I have a SPI microblaze core setup to talk to an ADC on a board.  I used code from examples, but something is still not right (though it compiles and debugs OK).  What bothers me is that if I write to a register a value, and then read from it, it seems like it is working, but when I scope the SDIO line I don't see any activity.  It is almost like the SPI device (in microblaze) is in loopback mode (which is an option) even though I haven't set it.  Can anyone spot my (most probably) sill mistake?  Thanks in advance!

 

int main() 
{
	int Status;
	u8 *BufferPtr;
	u8 UniqueValue;
	int Count;
	int Page;
	u8 Buffer[10];
	XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */


   Xil_ICacheEnable();
   Xil_DCacheEnable();

   print("---Entering main---\n\r");

	/*
	 * Initialize the SPI driver so that it is  ready to use.
	 */
	ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}
	Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
				  ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Set the SPI device as a master and in manual slave select mode such
	 * that the slave select signal does not toggle for every byte of a
	 * transfer, this must be done before the slave select is set
	 */
	Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Select the slave on the SPI bus, the EEPROM device so that it can be
	 * read and written using the SPI bus
	 */
	Status = XSpi_SetSlaveSelect(&Spi, SEEPROM_SPI_SELECT);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Start the SPI driver so that interrupts and the device are enabled
	 */
	XSpi_Start(&Spi);

	XSpi_IntrGlobalDisable(&Spi);

	Buffer[0] = 0x81;
	XSpi_WriteReg(&Spi.BaseAddr, 0x00, 0x81);
	Buffer[0] = XSpi_ReadReg(&Spi.BaseAddr, 0x00);

	xil_printf("Buffer[0] = 0x%x\r\n", (u8)Buffer[0]);


   print("---Exiting main---\n\r");

   Xil_DCacheDisable();
   Xil_ICacheDisable();

   return 0;
}

 

0 Kudos
15 Replies
Highlighted
Visitor
Visitor
13,335 Views
Registered: ‎06-29-2012

Hi,

can u say exactly what errors are u getting. I have run the code in my system, except some small errors like declaring spi and spi_ device it is working fine.

 

regards,

yagnik

0 Kudos
Highlighted
Voyager
Voyager
13,332 Views
Registered: ‎04-10-2012

yagnik,

 

Thanks for taking a look at it for me.  I actually am not getting an error, it just isn't working.  I can poke a value into a register and then read the value back, but I am not actually seeing anything going to/from the SPI device (for isntance I don't see CS or SDIO move at all during transfer).  I was convinced it was something in my code, but now I am starting to wonder if it is something lower (like in the XPS design).  Besides telling XPS that I have SPI, do I need to do anything else to set it up?  I left the memory mapping and all of that howeer XPS wanted to set it up.

 

Thanks a ton!!!

0 Kudos
Highlighted
Visitor
Visitor
13,330 Views
Registered: ‎06-29-2012

Hi,

Even if you have left memory and io mapping to XPS I think it's not a problem. You can just declare your spi device like

XSpi my_spi;

And define device_ID  like

#define SPI_DEVICE_ID       XPAR_SPI_0_DEVICE_ID

It might help you.

 

regards

yagnik

0 Kudos
Highlighted
Voyager
Voyager
13,326 Views
Registered: ‎04-10-2012

OK, thanks.  I do have that (I should have included my #defines for completeness).  When I have run selftests it seems to pass...

 

Here are some screenshots of my XPS setup (in case something is obviously wrong):

 

the bus interface in XPS

clip0000.jpg

 

The port view in XPS

clip0001.jpg

 

Address view in XPS

clip0002.jpg

 

From the MHS in XPS

clip0004.jpg

Also from the MHS

clip0003.jpg

0 Kudos
Highlighted
Visitor
Visitor
13,311 Views
Registered: ‎06-29-2012

Hi,

your XPS connections and HMS files looks fine(check if your clock input is differential ?). As you said earlier that there is no activity on SDIO, you can check the UCF file(pins allotted to nets) is correct or not .

 

regards,

yagnik

0 Kudos
Highlighted
Voyager
Voyager
13,287 Views
Registered: ‎04-10-2012

The clock input to the microblaze is differential (not sure why the XPS does that, but I haven't found a way to stop it).  I know the module is running fine because the serial JTAG print statements are coming through fine and I can blink an LED when I press a push button.

 

I believe the UCF is fine, and this morning I even routed the MISO, MOSI, CLK, and CS to 4 unused pins on a header and I still don't get any toggling on either the CLK or the CS.  I am starting to run out of things to question...

0 Kudos
Highlighted
Visitor
Visitor
13,262 Views
Registered: ‎06-29-2012

Hi,

I am too running out of probable problem areas. So have you found out what the problem was ? If you have, then do share with us.

 

Good day,

Yagnik

0 Kudos
Highlighted
Voyager
Voyager
13,219 Views
Registered: ‎04-10-2012

Nope, still having issues.  I can manually control the lines via Verilog, but trying to use them for SPI in microblaze is still not working...

0 Kudos
Highlighted
Voyager
Voyager
13,196 Views
Registered: ‎04-10-2012

Well, I finally got things working, so I thought I would leave it here in case someone else could find it useful.  

 

Here are some of the things i did and in the end it is working:

1 - Upgraded to 14.1 from 13.4 (don't know that it is a requirement, but I will stay working up here)

2 - Leave the SPI ports in the MHS file as IO instead of making them just I or O as I show in the images above

3 - In the Verilog code, make the SPI pins inout ports and connect them directly to the microblaze module (do not put a wire inbetween)

4 - Here is my code I used (key difference is the fact that readReg and writeReg I originally was trying to use is for reading/writing the FPGA spi device (and its low-level support), it can be made to work, but it is easier to use the transfer function:

#include <stdio.h>
#include <stdlib.h>
#include "xparameters.h"
#include "xil_cache.h"
#include "xspi.h"
#include "spi_header.h"
#include "xbasic_types.h"

#define SPI_DEVICE_ID		XPAR_SPI_0_DEVICE_ID
#define SPI_SELECT 0x01
#define LED_CHANNEL 1

int main() 
{
	static XSpi Spi;

	int Status;
	u8 WriteBuffer[10];
	u8 ReadBuffer[10];
	XSpi_Config *ConfigPtr;	/* Pointer to Configuration data */

	Xil_ICacheEnable();
	Xil_DCacheEnable();

	xil_printf("---Entering main---\n\r");

	 // Initialize the SPI driver so that it is  ready to use.
	ConfigPtr = XSpi_LookupConfig(SPI_DEVICE_ID);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	Status = XSpi_CfgInitialize(&Spi, ConfigPtr,ConfigPtr->BaseAddress);
	if (Status == XST_SUCCESS)
   	{
    		xil_printf("Spi Initialize success!\n\r");
   	}
   	else
   	{
    		xil_printf("Spi Initialize failed!\n\r");
   	}

	 // Set the SPI device as a master and in manual slave select mode such
	 // that the slave select signal does not toggle for every byte of a
	 // transfer, this must be done before the slave select is set
	Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION);
	if (Status != XST_SUCCESS) 
	{
		return XST_FAILURE;
	}

	// Select the slave on the SPI bus so that it can be
	// read and written using the SPI bus
	XSpi_GetSlaveSelect(&Spi);

	Status = XSpi_SetSlaveSelect(&Spi, SPI_SELECT);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	// Start the SPI driver so that interrupts and the device are enabled
	Status = XSpi_Start(&Spi);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	//disable global interrupts since we will use a polled approach
	XSpi_IntrGlobalDisable(&Spi);

	//Out ADC is setup to use the same pin (SDIO/MOSI) for both TX and RX, so we
	//need to turn the ADC from 2-wire to 3-wire (uses the SDO as a MISO)
	//We do this by setting the "write" bit as well as the upper bits of the address
	//to 0, and the rest of the address to 0, then we write the value 0x99 to that
	//address (see datasheet for part)
	WriteBuffer[0] = 0x00;
	WriteBuffer[1] = 0x00;
	WriteBuffer[2] = 0x99;
	Status = XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 3);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	//Now I will do a read of the 0x08 register to make sure I can read the chip ID
	//for this part. I set the "read" bit to 1 and the upper address bits to 0 and
	//the lower bits to 8. We have to tell the function to run for a 3 byte to make
	//sure the clock runs long enough for the read. The read value will be stored
	//in ReadBuffer[2]
	WriteBuffer[0] = 0x80;
	WriteBuffer[1] = 0x08;
	Status = XSpi_Transfer(&Spi, WriteBuffer, ReadBuffer, 3);
	Buffer[0] = ReadBuffer[2];
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	xil_printf("Buffer[2] = 0x%x\r\n", Buffer[2]);

	xil_printf("---Exiting main---\n\r");

	Xil_DCacheDisable();
	Xil_ICacheDisable();

	return 0;
}

And now everything is golden for me (for now).

Highlighted
Visitor
Visitor
5,538 Views
Registered: ‎06-29-2012

Hey,  good job.

I was also able to run the code. But in my case I think it was more of a software problem. Using right functions was the issue,  is what I think.

I too have used transfer function.

 

Cheers...

0 Kudos
Highlighted
Observer
Observer
4,062 Views
Registered: ‎05-02-2015

Hi

i'm using actualy a Microblase with the spi interface, i try to add the spi Ip core in the microblaze but i have  this warning:

WARNING:EDK:2137 - Peripheral xps_spi_0 is not accessible from any processor in the system. Check Bus Interface connections and address parameters. and i also I noticed the the spi core is connected to the PLB bus and not to the AXI. i try to build another system but still the same problem. can anyone help me to build my project.

Thanks

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
4,041 Views
Registered: ‎08-02-2007

hi billel

 

if you are trying to create a AXI sub-system then axi_quadspi should be used. since you are trying to connect xps_spi, the tool is not able to find PLB bus. so if you are using AXI interface, try configuring a AXI Quad SPI in standard mode.

 

for new queries it is recommended to create a new post.

 

--hem

----------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------------
0 Kudos
Highlighted
Mentor
Mentor
3,911 Views
Registered: ‎06-09-2011

Hi,

I know it's been a long time since you posted this thread. I have the same problem, I see no signaling on any of SPI pins. I modified my code to be exactly like what you implied as a successful one which is working properly. I did not made any changes on hardware and this happend suddenly after some software modifications!.

I am using EDK14.7

Any idea on this?

I would really appreciate it.

Thanks,
Hossein
0 Kudos
Highlighted
Newbie
Newbie
3,801 Views
Registered: ‎06-12-2015

i am new person on zynq soc , I am using spi0 for data transfer but i really don't know the commands through which i will trasnfer data and recive data to pl through spi. cuould you please help me.

0 Kudos
Highlighted
Voyager
Voyager
2,953 Views
Registered: ‎04-11-2016

Hi,

When using AXI quad SPI IP as slave, what modification come into your code? Any hint?

0 Kudos