microblaze spi core problem

  • Follow


Hello

I'm using Xilinx EDK 11.5 with xps_spi core version 2.01b. Core is 
correctly integrated in my SDK, I can see the signals on my DSO. 
Everything seems to be allright. But I've got a little software problem.

In SDK I transfer my data with the function "XSpi_Transfer(&mySPI, 
outBuffer, inBuffer, 2)" (see above). It works exactly one time and I 
get XST_SCCUSS back. But if I call XSpi_Transfer again, I get 
XST_DEVICE_BUSY back.

My program do the following steps:

1.) initalize SPI (function "XSpi_Initialize")
2.) set options (function "XSpi_SetOptions")
3.) select slave (function "XSpi_SetSlaveSelect")
4.) start SPI (function "XSpi_Start")
5.) transfer data (function "XSpi_Transfer")

Every function return XST_SUCCESS, but not Xspi_transfer when I call it 
the second time.

So my question? Is there any bug in the core or have I forgot something? 
I hope someone can help me. I tried to google, found a similar problem, 
but no solution.

Thanks a lot,

Tobias

C-Code:

#include <stdio.h>
#include "platform.h"
#include "xbasic_types.h"
#include "xstatus.h"
#include "xparameters.h"
#include "xspi.h"

void SPIini(void);
void pause(void);

XSpi mySPI;

int main()
{
     init_platform();
	
	print("SPI Test\n\r");
	pause();
	
	Xuint8 inBuffer[4] = {0x00, 0x00, 0x00, 0x00};
	Xuint8 outBuffer[4] = {0x00, 0xAA, 0xFF, 0xAA};
	
	XStatus status = XST_SUCCESS;
	
	SPIini();
	
	for(Xuint8 i=0; i<100; i++) {
		
		/* initialization */
		
		status = XSpi_Transfer(&mySPI, outBuffer, inBuffer, 2);
			
		switch(status)
		{
			case XST_SUCCESS: print("Status: Erfolgreich gesendet."); break;
			case XST_DEVICE_IS_STOPPED: print("Status: Device stopped\n\r"); break;
			case XST_DEVICE_BUSY: print("Status: Device busy\n\r"); break;
			case XST_SPI_NO_SLAVE: print("Status: Device no slave\n\r"); break;
		}
				
		pause();
	}

     cleanup_platform();

     return 0;
}

void SPIini(void)
{
	XStatus status = XST_SUCCESS;
	
	status = XSpi_Initialize(&mySPI, XPAR_TEST_SPI_DEVICE_ID);

	switch(status)
	{
		case XST_SUCCESS: print("Status: Erfolgreich initialisiert\n\r"); break;
		case XST_DEVICE_IS_STARTED: print("Status: Device is started\n\r"); break;
		case XST_DEVICE_NOT_FOUND: print("Status: Device not found\n\r"); break;
	}
	
	Xuint32 options = XSP_MASTER_OPTION;
	status = XSpi_SetOptions(&mySPI, options);

	switch(status)
	{
		case XST_SUCCESS: print("Status: Erfolgreich option gesetzt\n\r"); break;
		case XST_DEVICE_BUSY: print("Status: Device busy\n\r"); break;
		case XST_SPI_SLAVE_ONLY: print("Status: Slave only\n\r"); break;
	}
	
	XSpi_SetSlaveSelect(&mySPI, 1);
	XSpi_Start(&mySPI);
}

void pause(void)
{
	for(int i=0; i<CPU_FREQ; i++);
}
0
Reply Tobias 12/15/2010 3:05:53 PM

Tobias Baumann <ttobsen@hotmail.com> writes:

> Hello
>
> I'm using Xilinx EDK 11.5 with xps_spi core version 2.01b. Core is
> correctly integrated in my SDK, I can see the signals on my
> DSO. Everything seems to be allright. But I've got a little software
> problem.
>
> In SDK I transfer my data with the function "XSpi_Transfer(&mySPI,
> outBuffer, inBuffer, 2)" (see above). It works exactly one time and I
> get XST_SCCUSS back. But if I call XSpi_Transfer again, I get
> XST_DEVICE_BUSY back.
>

Maybe it is actually busy?  There's a FIFO in the SPI controller, so
the XSpi_Transfer call can return before the hardware has finished
sending.  Try checking the status flags before calling XSpi_Transfer
again.

If that's not the case, here's some other thoughts (without looking
deeply into your code, sorry!):

Have you provided your own XAssert handler function to report when
assertions fail - the Xilinx drivers are liberally sprinkled with
them, but the default action is just to hang.  If you look at the call
stack in the debugger, you can see what's going on, but I prefer to
have it pushed out over stdout as well...

I have this in main():
    XAssertSetCallback((XAssertCallback)myassert);

and this function elsewhere.

/* override the Xilinx xassert stub to report errors */
void myassert(char * file, int line)
{
    xil_printf("XASSERT: %s: line %d\r\n", file, line);
}

This may give some clues.

Also:

Have you enabled interrupts?  If so, is the driver expecting
interrupts?  As I recall, the 2.00.a driver didn't work in
non-interrupt mode (it re-enabled the SPI interrupts at the end of a
transmit, irrespective of the interrupt status on entry :) but I think
that was fixed in 2.00.b

Have you provided a StatusHandler function for the spi driver? I seem
to recall doing this helped me debug a similar problem.

On the up side - you at least have all the source to the driver, so
you can single step everything through :)

> void pause(void)
> {
> 	for(int i=0; i<CPU_FREQ; i++);
> }

This is not the world's greatest pause function!  The compiler will
just optimise the loop away (although probably not the function call
itself).

You need a timer in your system that you can watch to see elapsed
time.

Cheers,
Martin

-- 
martin.j.thompson@trw.com 
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.co.uk/capabilities/39-electronic-hardware
0
Reply Martin 12/16/2010 10:01:46 AM


I have successfully used the SPI peripheral with a SPI Flash.  The
only difference that I can see is a call to disable the interrupts
since I use the peripheral in polled mode:
	XSpi_mIntrGlobalDisable(&mySpi);

Here's my instantiation from my MHS.  I turned on the FIFOs and have
an SCK Ratio of 16 (this is from EDK 10):

BEGIN xps_spi
 PARAMETER INSTANCE =3D SPI_FLASH
 PARAMETER C_FIFO_EXIST =3D 1
 PARAMETER C_SCK_RATIO =3D 16
 PARAMETER HW_VER =3D 2.01.b
 PARAMETER C_BASEADDR =3D 0x83400000
 PARAMETER C_HIGHADDR =3D 0x8340ffff
 BUS_INTERFACE SPLB =3D mb_plb
 PORT SPISEL =3D net_vcc
 PORT SCK =3D fpga_0_SPI_FLASH_SCK_pin
 PORT MISO =3D fpga_0_SPI_FLASH_MISO_pin
 PORT MOSI =3D fpga_0_SPI_FLASH_MOSI_pin
 PORT SS =3D fpga_0_SPI_FLASH_SS_pin
END

Here's the complete example if you are interested:
   www.em.avnet.com/spartan3a-evl --> > MicroBlaze Serial Flash Test

Bryan

On Dec 15, 10:05=A0am, Tobias Baumann <ttob...@hotmail.com> wrote:
> Hello
>
> I'm using Xilinx EDK 11.5 with xps_spi core version 2.01b. Core is
> correctly integrated in my SDK, I can see the signals on my DSO.
> Everything seems to be allright. But I've got a little software problem.
>
> In SDK I transfer my data with the function "XSpi_Transfer(&mySPI,
> outBuffer, inBuffer, 2)" (see above). It works exactly one time and I
> get XST_SCCUSS back. But if I call XSpi_Transfer again, I get
> XST_DEVICE_BUSY back.
>
> My program do the following steps:
>
> 1.) initalize SPI (function "XSpi_Initialize")
> 2.) set options (function "XSpi_SetOptions")
> 3.) select slave (function "XSpi_SetSlaveSelect")
> 4.) start SPI (function "XSpi_Start")
> 5.) transfer data (function "XSpi_Transfer")
>
> Every function return XST_SUCCESS, but not Xspi_transfer when I call it
> the second time.
>
> So my question? Is there any bug in the core or have I forgot something?
> I hope someone can help me. I tried to google, found a similar problem,
> but no solution.
>
> Thanks a lot,
>
> Tobias
>
> C-Code:
>
> #include <stdio.h>
> #include "platform.h"
> #include "xbasic_types.h"
> #include "xstatus.h"
> #include "xparameters.h"
> #include "xspi.h"
>
> void SPIini(void);
> void pause(void);
>
> XSpi mySPI;
>
> int main()
> {
> =A0 =A0 =A0init_platform();
>
> =A0 =A0 =A0 =A0 print("SPI Test\n\r");
> =A0 =A0 =A0 =A0 pause();
>
> =A0 =A0 =A0 =A0 Xuint8 inBuffer[4] =3D {0x00, 0x00, 0x00, 0x00};
> =A0 =A0 =A0 =A0 Xuint8 outBuffer[4] =3D {0x00, 0xAA, 0xFF, 0xAA};
>
> =A0 =A0 =A0 =A0 XStatus status =3D XST_SUCCESS;
>
> =A0 =A0 =A0 =A0 SPIini();
>
> =A0 =A0 =A0 =A0 for(Xuint8 i=3D0; i<100; i++) {
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* initialization */
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 status =3D XSpi_Transfer(&mySPI, outBuffe=
r, inBuffer, 2);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch(status)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_SUCCESS: print("=
Status: Erfolgreich gesendet."); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_DEVICE_IS_STOPPE=
D: print("Status: Device stopped\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_DEVICE_BUSY: pri=
nt("Status: Device busy\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_SPI_NO_SLAVE: pr=
int("Status: Device no slave\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pause();
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0cleanup_platform();
>
> =A0 =A0 =A0return 0;
>
> }
>
> void SPIini(void)
> {
> =A0 =A0 =A0 =A0 XStatus status =3D XST_SUCCESS;
>
> =A0 =A0 =A0 =A0 status =3D XSpi_Initialize(&mySPI, XPAR_TEST_SPI_DEVICE_I=
D);
>
> =A0 =A0 =A0 =A0 switch(status)
> =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_SUCCESS: print("Status: Erfolgre=
ich initialisiert\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_DEVICE_IS_STARTED: print("Status=
: Device is started\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_DEVICE_NOT_FOUND: print("Status:=
 Device not found\n\r"); break;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 Xuint32 options =3D XSP_MASTER_OPTION;
> =A0 =A0 =A0 =A0 status =3D XSpi_SetOptions(&mySPI, options);
>
> =A0 =A0 =A0 =A0 switch(status)
> =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_SUCCESS: print("Status: Erfolgre=
ich option gesetzt\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_DEVICE_BUSY: print("Status: Devi=
ce busy\n\r"); break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 case XST_SPI_SLAVE_ONLY: print("Status: S=
lave only\n\r"); break;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 XSpi_SetSlaveSelect(&mySPI, 1);
> =A0 =A0 =A0 =A0 XSpi_Start(&mySPI);
>
> }
>
> void pause(void)
> {
> =A0 =A0 =A0 =A0 for(int i=3D0; i<CPU_FREQ; i++);
>
> }

0
Reply Bryan 12/20/2010 9:42:07 PM

Hi Martin and Bryan

You both were right. I had to disable the interrupts with 
Xspi_mIntrGlobalDisable(&mySpi) and now it works fine. Thanks a lot to you!

But unfortunately I have a new problem. I want to stream data to a W-LAN 
module, so I need a high throughput to max out my performance. The SPI 
core is very slow, so I can't use the high performance of my W-LAN 
module. (I get a throughput of 30kB/s, this is much to slow).

Has someone an idea how to increase the throughput of my system? A fine 
solution would be, sending data directly from rams and/or registers via 
SPI to my module. Maybe DMA is the right keyword, but I'm not sure, 
because I'm a total beginner of programming microblaze and IP cores.

Maybe someone has a hint in which direction I have to search, for 
finding a solution.

Thanks a lot!

Tobias
0
Reply Tobias 12/21/2010 3:02:18 PM

Some improvement can be made by decreasing the SCK Ratio, but you're
still dealing with the PLB.  If this is Spartan-6 or Virtex-6, you
could look at switching to AXI.  You could also look at a designing
your own simple SPI peripheral and connect to MicroBlaze via FSL.

Bryan

On Dec 21, 10:02=A0am, Tobias Baumann <ttob...@hotmail.com> wrote:
> Hi Martin and Bryan
>
> You both were right. I had to disable the interrupts with
> Xspi_mIntrGlobalDisable(&mySpi) and now it works fine. Thanks a lot to yo=
u!
>
> But unfortunately I have a new problem. I want to stream data to a W-LAN
> module, so I need a high throughput to max out my performance. The SPI
> core is very slow, so I can't use the high performance of my W-LAN
> module. (I get a throughput of 30kB/s, this is much to slow).
>
> Has someone an idea how to increase the throughput of my system? A fine
> solution would be, sending data directly from rams and/or registers via
> SPI to my module. Maybe DMA is the right keyword, but I'm not sure,
> because I'm a total beginner of programming microblaze and IP cores.
>
> Maybe someone has a hint in which direction I have to search, for
> finding a solution.
>
> Thanks a lot!
>
> Tobias

0
Reply Bryan 12/22/2010 4:34:26 PM

Am 22.12.2010 17:34, schrieb Bryan:
> Some improvement can be made by decreasing the SCK Ratio, but you're
> still dealing with the PLB.  If this is Spartan-6 or Virtex-6, you
> could look at switching to AXI.  You could also look at a designing
> your own simple SPI peripheral and connect to MicroBlaze via FSL.
>

I'm working with a Spartan 3A-DSP.

After optimizing the settings of the SPI-Core I get a much higher 
throughput (maybe 500kB/s to 1MB/s, I still have to measure it).

I thought that I have to make my own SPI peripheral to optimize my 
problem, but I hoped that there is a finshed solution.

Thanks a lot.

Tobias
0
Reply Tobias 12/23/2010 10:43:36 AM

5 Replies
859 Views

(page loaded in 0.1 seconds)

Similiar Articles:













7/25/2012 7:18:07 AM


Reply: