UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Adventurer
Adventurer
5,352 Views
Registered: ‎08-17-2009

SPI Module does not transmit

Jump to solution

Hi,

 

I am using the PowerPC in an Virtex5 and have an SPI module attached to it.

However, I cannot get it to transmit anything. Not even the Enable bit gets selected.

The only thing I can see in the hardware, is that the clock is enabled during the XSpi_SelfTest.

If I use the polled mode, the XSpi_Transfer does not return, if I use the interrupt mode, the status register has the XSP_SR_TX_FULL bit set after I called XSpi_Transfer, but nothing is transferred and the register stays in that state forever.

 

What am I doing wrong here?

 

My C-Code is:

 

static XSpi        SpiInstance;     /* The instance of the SPI device */
static XSpi_Stats  SpiStats;
u8 ReadBuffer[4];
u8 WriteBuffer[4];

void printStats()
{
    u8 SReg;
    XSpi_GetStats(&SpiInstance, &SpiStats);
    SReg = XSpi_mGetStatusReg(&SpiInstance);
    
    xil_printf("StatReg: %x. SpiStats: Transf %d MdFlt %d NumInt %d RecOvr %d SlvMdFlt %d XmitUnd %d\n\r",  
                SReg,
                SpiStats.BytesTransferred, SpiStats.ModeFaults, SpiStats.NumInterrupts,
                SpiStats.RecvOverruns, SpiStats.SlaveModeFaults, SpiStats.XmitUnderruns);
}

int main()
{
    int SPI_Status;
    
    init_platform();

    print("------------------\n\rSPI init...\n\r");
    SPI_Status = XSpi_Initialize(&SpiInstance, XPAR_XPS_SPI_0_ADC_DEVICE_ID);
    if (SPI_Status == XST_SUCCESS) print ("Success.\n\r");
    else print("failure\n\r");

    SPI_Status = XSpi_SelfTest(&SpiInstance);
    if (SPI_Status == XST_SUCCESS) print(" Self Test OK \r\n");
    
    XSpi_Start(&SpiInstance);
    print("Started.\n\r");
    
    XSpi_mSetControlReg(&SpiInstance, XSP_CR_MASTER_MODE_MASK & XSP_CR_ENABLE_MASK & XSP_CR_LOOPBACK_MASK
                        & XSP_CR_MANUAL_SS_MASK);
    //XSpi_mIntrGlobalDisable(&SpiInstance);
    
    ReadBuffer[0] = 0;
    WriteBuffer[0] = 0x12;//345678;
    
    SPI_Status = XSpi_SetSlaveSelect(&SpiInstance, 0x0001);
    xil_printf("Slave Selected, Status: %d  \n\r", SPI_Status);
    
    SPI_Status = XSpi_SetSlaveSelect(&SpiInstance, 0x0000);
    xil_printf("Slave Deselected, Status: %d  \n\r", SPI_Status);
    
    SPI_Status = XSpi_SetSlaveSelect(&SpiInstance, 0x0001);
    xil_printf("Slave Selected, Status: %d  \n\r", SPI_Status);
    
    printStats();
    
    xil_printf("Transmitting now %x, ReadBuffer is %x \n\r", WriteBuffer[0], ReadBuffer[0]);
    
    WritePtr = (u8*)WriteBuffer;
    ReadPtr = (u8*)ReadBuffer;
    
    SPI_Status = XSpi_Transfer(&SpiInstance, WriteBuffer, ReadBuffer, 1);
    
    xil_printf("Status: %d  Read: %x\n\r", SPI_Status, ReadBuffer[0]);


    printStats();

 

 

 

In case this should be important, here are the SPI parameters:

 

/* Canonical definitions for peripheral XPS_SPI_0_ADC */
#define XPAR_SPI_0_DEVICE_ID XPAR_XPS_SPI_0_ADC_DEVICE_ID
#define XPAR_SPI_0_BASEADDR 0x85000000
#define XPAR_SPI_0_HIGHADDR 0x8500FFFF
#define XPAR_SPI_0_FIFO_EXIST 1
#define XPAR_SPI_0_SPI_SLAVE_ONLY 0
#define XPAR_SPI_0_NUM_SS_BITS 1
#define XPAR_SPI_0_NUM_TRANSFER_BITS 32

 

I also tried to send 4 bytes in the XSpi_Transfer command because I have defined 32 bit datawords, but the only thing that changes is that the XSP_SR_TX_FULL bit is not set in the status reg (but the XSP_SR_TX_EMPTY also stays 0 after the transmit command).

 

Any hint would be highly appreciated!

Stefan

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Newbie shebli
Newbie
6,611 Views
Registered: ‎03-04-2011

Re: SPI Module does not transmit

Jump to solution

Hi Stefan,

1) I would avoid using any call to XSpi_mSetControlReg.

2) Assuming you operate in master mode, I would add a call to:

XSpi_SetOptions(&SpiInstance, XSP_MASTER_OPTION | XSP_CLK_ACTIVE_LOW_OPTION);

3) I would also call:

XSpi_Enable(&SpiInstance);

4) I would connect the XSpi interrupt handler to the right interrupt in your system. In my case, using VxWorks, and based on the order in which you instantiate your Spi firmware (compared for instance t to ltemac, I2C, etc.) the XSpi module is connected to interrupt level number XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR and connect the XSpi interrupt handler by calling:

intConnect(
(VOIDFUNCPTR*) ,
(VOIDFUNCPTR) XSpi_InterruptHandler,
(int) &SpiInstance
); // VxWorks call

5) I would not forget to enable the interrupt level in the OS (here VxWorks):

intEnable(XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR); // VxWorks call

6) Of course, you need to select the slave mask corresponding to your device (mine is 0x00000001) and to start your device (as you have properly done):
XSpi_SetSlaveSelect(&SpiInstance, 0x00000001u);
XSpi_Start(&SpiInstance);

7) Last but not least, you have to provide the XSpi interrupt handler with a routine of your own that will be called at the end of the interrupt handler (within interrupt context). In my case, I installed the following handler, which just signals a semaphore that my main function is waiting on after initiating the XSpi data transfer. And don't forget to aknowledge the interrupt: I do it by calling the VxWorks function intDisable):

--> This is my callback function:

void spiXferCallback(void * /*CallBackRef*/, u32 statusEvent, unsigned int byteCount)
{
intDisable(XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR); // VxWorks call
semGive(myXSpiSemaphore); // VxWorks call
}

--> This is how you install it in the XSpi driver:

XSpi_SetStatusHandler(&SpiInstance, XPAR_XPS_SPI_0_ADC_DEVICE_ID, spiXferCallback);

--> This is how I wait for my semaphore after calling the SPI transfer function (I do my error handling using C++ exceptions, but that's not relevant here):

if ((st = XSpi_Transfer(&SpiInstance, (u8*) &snd, (u8*) &rcv, sizeof(u32)) != XST_SUCCESS))
throw XSpiException(st, "XSpi_Transfer");

printf("-- Waiting for interrupt...\n");
semTake(myXSpiSemaphore, WAIT_FOREVER); // VxWorks call
printf("Got it!\n");

Hope it helps! Xilinx should really give us some examples!

Cheers,
Shebli.





View solution in original post

3 Replies
Highlighted
Newbie shebli
Newbie
6,612 Views
Registered: ‎03-04-2011

Re: SPI Module does not transmit

Jump to solution

Hi Stefan,

1) I would avoid using any call to XSpi_mSetControlReg.

2) Assuming you operate in master mode, I would add a call to:

XSpi_SetOptions(&SpiInstance, XSP_MASTER_OPTION | XSP_CLK_ACTIVE_LOW_OPTION);

3) I would also call:

XSpi_Enable(&SpiInstance);

4) I would connect the XSpi interrupt handler to the right interrupt in your system. In my case, using VxWorks, and based on the order in which you instantiate your Spi firmware (compared for instance t to ltemac, I2C, etc.) the XSpi module is connected to interrupt level number XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR and connect the XSpi interrupt handler by calling:

intConnect(
(VOIDFUNCPTR*) ,
(VOIDFUNCPTR) XSpi_InterruptHandler,
(int) &SpiInstance
); // VxWorks call

5) I would not forget to enable the interrupt level in the OS (here VxWorks):

intEnable(XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR); // VxWorks call

6) Of course, you need to select the slave mask corresponding to your device (mine is 0x00000001) and to start your device (as you have properly done):
XSpi_SetSlaveSelect(&SpiInstance, 0x00000001u);
XSpi_Start(&SpiInstance);

7) Last but not least, you have to provide the XSpi interrupt handler with a routine of your own that will be called at the end of the interrupt handler (within interrupt context). In my case, I installed the following handler, which just signals a semaphore that my main function is waiting on after initiating the XSpi data transfer. And don't forget to aknowledge the interrupt: I do it by calling the VxWorks function intDisable):

--> This is my callback function:

void spiXferCallback(void * /*CallBackRef*/, u32 statusEvent, unsigned int byteCount)
{
intDisable(XPAR_XPS_INTC_0_XPS_SPI_0_IP2INTC_IRPT_INTR); // VxWorks call
semGive(myXSpiSemaphore); // VxWorks call
}

--> This is how you install it in the XSpi driver:

XSpi_SetStatusHandler(&SpiInstance, XPAR_XPS_SPI_0_ADC_DEVICE_ID, spiXferCallback);

--> This is how I wait for my semaphore after calling the SPI transfer function (I do my error handling using C++ exceptions, but that's not relevant here):

if ((st = XSpi_Transfer(&SpiInstance, (u8*) &snd, (u8*) &rcv, sizeof(u32)) != XST_SUCCESS))
throw XSpiException(st, "XSpi_Transfer");

printf("-- Waiting for interrupt...\n");
semTake(myXSpiSemaphore, WAIT_FOREVER); // VxWorks call
printf("Got it!\n");

Hope it helps! Xilinx should really give us some examples!

Cheers,
Shebli.





View solution in original post

Adventurer
Adventurer
5,314 Views
Registered: ‎08-17-2009

Re: SPI Module does not transmit

Jump to solution

Hi shebli,

 

thank you so much for your comprehensive answer!

After finally finding the examples from Xilinx (which are by the way, located in the Program installation directory, in my case at:

C:\Xilinx\ISE11\EDK\sw\XilinxProcessorIPLib\drivers\spi_v2_01_b\examples)

I found that my main problem was the very stupid mistake of using & instead of | to connect the bitmasks for XSpi_mSetControlReg (which I then also replaced by XSpi_SetOptions as you are suggesting).

 

And thank you very much for the explanation of the interrupt handling, I put this issue up for later (only use polling mode in the moment), and now I'm less afraid of it.

 

Best regards,

Stefan

 

 

 

0 Kudos
Visitor celojan
Visitor
4,978 Views
Registered: ‎02-07-2011

Re: SPI Module does not transmit

Jump to solution
Its importan review the caracteristics of the devices that you can transmit...!! The clock phase and polarity..!!! Remenber thar the ss vector is enable in low state.
0 Kudos