[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [microblaze-uclinux] spi and spidev usage



Welcome back Matt.

> Sorry for take several weeks to get back to your last reply.  I have been taking exams and on traveling.

Sic, and I thought you got it running.
I hope you had success with your exams instead.


> When you say look for the hardware or FPGA-configuration, what do you suggest I specifically check?

Just the stupid things: wrong pin assignment, missing IO-voltage, wrong nets connected, missed errors or warnings during synthesis. Don't know.
You could also try the other SPI-bus, your flash is working? Just be creative to localize the problem.


> I've checked all my hardware settings against a working EDK project I have where I used the SPI core (without uCLInux).

So the hardware-part must be correct?
I would not continue with Linux before knowing for sure that the hardware and EDK-project are fine.


> Do you mean xspi_intr_example?  I found a version under my ISE directory.  I've already tested the SPI core without linux using a previous project and it works just fine.  However, in that program I use calls to XIO_Out32 at the certain memory addresses for the SPI core.  Do you think using the XSpi example script could give a different result?

Just use an arbitrary example. I think you found one. 
I only tried this higher-level example, no idea about direct access.


> I'm using an old SPI-core (1.11a). I don't know if there is a driver-problem with the new one or if the behavior is different.
> I checked my SPI IP core, and I have the OPB SPI core version 1.00e.  Is my version older than yours?  I'm using Xilinx ISE 9.1i and according to Xilinx's download site, I have the latest IP core service pack. 

I'm using xps_spi with PLB, 1.00.a in ISE 10.1.1. The version posted before was the driver. Sorry. I don't know more about other versions or the OPB-things. OPB is rather old, isn't it?


>     /*
>      * Transmit the data.
>      */
>     TransferInProgress = XTRUE;
>     XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);
> 
>     /*
>      * Wait for the transmission to be complete.
>      */
>     while (TransferInProgress);
> 

While will never be left if you don't have interrupts.

Make somehow sure to run XSpi_Transfer() more often and wait each time to complete the transmission and a bit longer. This makes observation easier.


> static XStatus SpiSetupIntrSystem(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
>                                   Xuint16 SpiIntrId)
...
>     /*
>      * Enable the interrupt for the SPI device.
>      */
>     XIntc_Enable(IntcInstancePtr, SpiIntrId);
> 

I have an additional microblaze_enable_interrupts() here.


> So far, I don't see anything on the pin output when I run this code.

Not so good. But maybe you just missed it due to a trigger issue on the single transmission (see above).

> I commented out some of the interrupt exception code since I don't have that set up in my EDK project.

I might be wrong but I think you will need interrupts for the Linux-driver anyway.


Carsten.



De: owner-microblaze-uclinux@xxxxxxxxxxxxxx [mailto:owner-microblaze-uclinux@xxxxxxxxxxxxxx] En nombre de Matt Staniszewski
Enviado el: martes, 31 de marzo de 2009 7:27
Para: microblaze-uclinux@xxxxxxxxxxxxxx
Asunto: Re: [microblaze-uclinux] spi and spidev usage

Hi Carsten,

Here's my modified xspi_intr_example code.  I have two SPI interfaces set up, one for a DAC, the other for external pins to test.  I commented out some of the interrupt exception code since I don't have that set up in my EDK project.  I copied the hardware directly from the petalinux reference design that I've been using and then removed all the software and added my own project.

--------------------------------------------------------------

/* $Id: xspi_intr_example.c,v 1.2 2006/06/01 09:42:27 svemula Exp $ */
/******************************************************************************
*
*       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,
*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*       FOR A PARTICULAR PURPOSE.
*
*       (c) Copyright 2002-2006  Xilinx Inc.
*       All rights reserved.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xspi_intr_example.c
*
*
* This file contains a design example using the Spi driver (XSpi) and the Spi
* device using the interrupt mode.
*
* This example works with a PPC processor. Refer the examples of Interrupt
* controller (XIntc) for an example of using interrupts with the MicroBlaze
* processor.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.01a sv   05/29/06 First release for Test App Integration
*                     for Interrupt examples
*</pre>
******************************************************************************/

/***************************** Include Files *********************************/

#include "xparameters.h"        /* XPAR parameters */
#include "xspi.h"               /* SPI device driver */
#include "xintc.h"              /* Interrupt controller device driver */

//#ifdef __MICROBLAZE__
#include "mb_interface.h"
//#else
//#include "xexception_l.h"
//#endif

/************************** Constant Definitions *****************************/

/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#ifndef TESTAPP_GEN
/* SPI 0 Settings */
//#define SPI_DEVICE_ID           XPAR_OPB_SPI_0_DEVICE_ID
//#define INTC_DEVICE_ID          XPAR_INTC_SINGLE_DEVICE_ID
//#define SPI_IRPT_INTR           XPAR_OPB_SPI_0_IP2INTC_IRPT_MASK
/* SPI 1 Settings */
#define SPI_DEVICE_ID           XPAR_OPB_SPI_1_DEVICE_ID
#define INTC_DEVICE_ID          XPAR_INTC_SINGLE_DEVICE_ID
#define SPI_IRPT_INTR           XPAR_OPB_SPI_1_IP2INTC_IRPT_MASK
#endif

/*
 *  This is the size of the buffer to be transmitted/received in this example.
 */
#define BUFFER_SIZE             0x50


/**************************** Type Definitions *******************************/

/*
 * The following data type is used to send and receive data on the SPI
 * interface.
 */
typedef Xuint8 DataBuffer[BUFFER_SIZE];


/***************** Macros (Inline Functions) Definitions *********************/


/************************** Function Prototypes ******************************/

XStatus SpiIntrExample(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
                       Xuint16 SpiDeviceId, Xuint16 SpiIntrId);

void SpiIntrHandler(void *CallBackRef, Xuint32 StatusEvent, Xuint32 ByteCount);

static XStatus SpiSetupIntrSystem(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
                                  Xuint16 SpiIntrId);

static void SpiDisableIntrSystem(XIntc *IntcInstancePtr, Xuint16 SpiIntrId);




/************************** Variable Definitions *****************************/

/*
 * The instances to support the device drivers are global such that the
 * are initialized to zero each time the program runs.
 */
#ifndef TESTAPP_GEN
static XIntc IntcInstance;     /* The instance of the Interrupt Controller */
static XSpi  SpiInstance;      /* The instance of the SPI device */
#endif

/*
 * The following variables are shared between non-interrupt processing and
 * interrupt processing such that they must be global.
 */
volatile Xboolean TransferInProgress;

/*
 * The following variable tracks any errors that occur during interrupt
 * processing
 */
int Error;

/*
 * The following variables are used to read and write to the  Spi device, they
 * are global to avoid having large buffers on the stack.
 */
Xuint8 ReadBuffer[BUFFER_SIZE];
Xuint8 WriteBuffer[BUFFER_SIZE];


/*****************************************************************************/
/**
*
* Main function to call the Spi interrupt example.
*
* @param    None
*
* @return   XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note     None
*
******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
    XStatus Status;

    /*
     * Run the Spi Interrupt example.
     */
    Status = SpiIntrExample(&IntcInstance,
                            &SpiInstance,
                            SPI_DEVICE_ID,
                            SPI_IRPT_INTR);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    return XST_SUCCESS;
}
#endif

/*****************************************************************************/
/**
*
* This function does a minimal test on the Spi device and driver as a
* design example. The purpose of this function is to illustrate how to use
* the XSpi component using the interrupt mode.
*
* This function sends data and expects to receive the same data.
*
*
* @param    IntcInstancePtr is a pointer to the instance of the INTC component.
* @param    SpiInstancePtr is a pointer to the instance of Spi component.
* @param    SpiDeviceId is the Device ID of the Spi Device and is the
*           XPAR_<SPI_instance>_DEVICE_ID value from xparameters.h.
* @param    SpiIntrId is the interrupt Id and is typically
*           XPAR_<INTC_instance>_<SPI_instance>_IP2INTC_IRPT_INTR
*           value from xparameters.h .
*
* @return   XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
******************************************************************************/
XStatus SpiIntrExample(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
                       Xuint16 SpiDeviceId, Xuint16 SpiIntrId)
{
    XStatus Status;
    Xuint32 Count;
    Xuint8 Test;

    /*
     * Initialize the SPI driver so that it's ready to use,
     * specify the device ID that is generated in xparameters.h
     */
    Status = XSpi_Initialize(SpiInstancePtr, SpiDeviceId);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }


    /*
     * Perform a self-test to ensure that the hardware was built correctly.
     */
    Status = XSpi_SelfTest(SpiInstancePtr);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }


    /*
     * Connect the Spi device to the interrupt subsystem such that
     * interrupts can occur. This function is application specific.
     */
    //Status = SpiSetupIntrSystem(IntcInstancePtr,
    //                            SpiInstancePtr,
    //                            SpiIntrId);
    //if (Status != XST_SUCCESS)
    //{
    //    return XST_FAILURE;
    //}

    /*
     * Setup the handler for the SPI that will be called from the interrupt
     * context when an SPI status occurs, specify a pointer to the SPI driver
     * instance as the callback reference so the handler is able to access the
     * instance data.
     */
    XSpi_SetStatusHandler(SpiInstancePtr, SpiInstancePtr,
                         (XSpi_StatusHandler)SpiIntrHandler);

    /*
     * ADDON: Set the Spi device as a master (NO loopback).
     */
    Status = XSpi_SetOptions(SpiInstancePtr,
                             XSP_MASTER_OPTION);
    /*
     * Set the Spi device as a master and in loopback mode.
     */
    //Status = XSpi_SetOptions(SpiInstancePtr,
    //                         XSP_MASTER_OPTION | XSP_LOOPBACK_OPTION);
    
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }


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

    /*
     * Initialize the write buffer with pattern to write, initialize the
     * read buffer to zero so it can be verified after the read, the
     * Test value that is added to the unique value allows the value to be
     * changed in a debug environment.
     */
    Test = 0x10;
    for (Count = 0; Count < BUFFER_SIZE; Count++)
    {
        WriteBuffer[Count] = (Xuint8)(Count + Test);
        ReadBuffer[Count] = 0;
    }

    /* ADDON: Call set SPI slave select before transfer. */
    //Status = XSpi_SetSlaveSelect(SpiInstancePtr, 0x0001);   // SPI 0: DAC
    Status = XSpi_SetSlaveSelect(SpiInstancePtr, 0x0002); // SPI 1: Pins

    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }


    /*
     * Transmit the data.
     */
    TransferInProgress = XTRUE;
    XSpi_Transfer(SpiInstancePtr, WriteBuffer, ReadBuffer, BUFFER_SIZE);

    /*
     * Wait for the transmission to be complete.
     */
    while (TransferInProgress);


    /*
     * Disable the Spi interrupt.
     */
    SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);

    /*
     * Compare the data received with the data that was transmitted.
     */
    for (Count = 0; Count < BUFFER_SIZE; Count++)
    {
        if (WriteBuffer[Count] != ReadBuffer[Count])
        {
            return XST_FAILURE;
        }
    }

    return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param    CallBackRef is the upper layer callback reference passed back
*           when the callback function is invoked.
* @param    StatusEvent is the event that just occurred.
* @param    ByteCount is the number of bytes transferred up until the event
*           occurred.
*
* @return   None.
*
* @note     None.
*
******************************************************************************/
void SpiIntrHandler(void *CallBackRef, Xuint32 StatusEvent, Xuint32 ByteCount)
{
    /*
     * Indicate the transfer on the SPI bus is no longer in progress
     * regardless of the status event.
     */
    TransferInProgress = XFALSE;

    /*
     * If the event was not transfer done, then track it as an error.
     */
    if (StatusEvent != XST_SPI_TRANSFER_DONE)
    {
        Error++;
    }
}


/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller.  The
* user should modify this function to fit the application.
*
* @param    IntcInstancePtr is a pointer to the instance of the Intc device.
* @param    SpiInstancePtr is a pointer to the instance of the Spi device.
* @param    SpiIntrId is the interrupt Id and is typically
*           XPAR_<INTC_instance>_<SPI_instance>_IP2INTC_IRPT_INTR
*           value from xparameters.h
*
* @return   XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note     None
*
******************************************************************************/
static XStatus SpiSetupIntrSystem(XIntc *IntcInstancePtr, XSpi *SpiInstancePtr,
                                  Xuint16 SpiIntrId)
{
    XStatus Status;

#ifndef TESTAPP_GEN
    /*
     * Initialize the interrupt controller driver so that it is ready to use.
     */
    Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
#endif

    /*
     * Connect a device driver handler that will be called when an interrupt
     * for the device occurs, the device driver handler performs the specific
     * interrupt processing for the device.
     */
    Status = XIntc_Connect(IntcInstancePtr, SpiIntrId,
                           (XInterruptHandler)XSpi_InterruptHandler,
                           (void *)SpiInstancePtr);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

#ifndef TESTAPP_GEN
    /*
     * Start the interrupt controller such that interrupts are enabled for
     * all devices that cause interrupts, specific real mode so that
     * the SPI can cause interrupts through the interrupt controller.
     */
    Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
#endif

    /*
     * Enable the interrupt for the SPI device.
     */
    XIntc_Enable(IntcInstancePtr, SpiIntrId);

#ifndef TESTAPP_GEN


    /*
     * Initialize the PPC exception table.
     */
    //XExc_Init();

    /*
     * Register the interrupt controller handler with the exception table.
     */
    //XExc_RegisterHandler(XEXC_ID_NON_CRITICAL_INT,
    //                    (XExceptionHandler)XIntc_InterruptHandler,
    //                    IntcInstancePtr);

    /*
     * Enable non-critical exceptions.
     */
    //XExc_mEnableExceptions(XEXC_NON_CRITICAL);

#endif /* TESTAPP_GEN */

    return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Spi device.
*
* @param    IntcInstancePtr is the pointer to the instance of the INTC
*           component.
* @param    SpiIntrId is the interrupt Id and is typically
*           XPAR_<INTC_instance>_<SPI_instance>_IP2INTC_IRPT_INTR
*           value from xparameters.h
*
* @return   None
*
* @note     None
*
******************************************************************************/
static void SpiDisableIntrSystem(XIntc *IntcInstancePtr, Xuint16 SpiIntrId)
{

    /*
     * Disconnect and disable the interrupt for the Spi device.
     */
    XIntc_Disconnect(IntcInstancePtr, SpiIntrId);
}

--------------------------------------------------------------

So far, I don't see anything on the pin output when I run this code.  I'll try a scope too just to see if something is going on.  Thanks!

Matt

On Mon, Mar 30, 2009 at 20:19, Matt Staniszewski <matt.staniszewski@xxxxxxxxx> wrote:
Hi Carsten,

Sorry for take several weeks to get back to your last reply.  I have been taking exams and on traveling.

Unfortunately I don't remember what the SCLK does when idle. The other lines high is good and I would expect SCLK to do the same. When starting a transmission first SS for one device goes low, later clock and data appear. If SS and data are missing too I would look for the driver. If only clock is missing you might rather look for hardware or FPGA-configuration. 
When you say look for the hardware or FPGA-configuration, what do you suggest I specifically check?  I've checked all my hardware settings against a working EDK project I have where I used the SPI core (without uCLInux).
 
You can test the SPI-core without linux. There is an example in Xilinx-ISE (I used xps_intr_example.c). It is a loopback test but if you remove the loopback option and add a call to XSpi_SetSlaveSelect before Transfer you can see the output.
Do you mean xspi_intr_example?  I found a version under my ISE directory.  I've already tested the SPI core without linux using a previous project and it works just fine.  However, in that program I use calls to XIO_Out32 at the certain memory addresses for the SPI core.  Do you think using the XSpi example script could give a different result?
I'm using an old SPI-core (1.11a). I don't know if there is a driver-problem with the new one or if the behavior is different.
I checked my SPI IP core, and I have the OPB SPI core version 1.00e.  Is my version older than yours?  I'm using Xilinx ISE 9.1i and according to Xilinx's download site, I have the latest IP core service pack. 

Thanks!

Matt



___________________________
microblaze-uclinux mailing list
microblaze-uclinux@xxxxxxxxxxxxxx
Project Home Page : http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux
Mailing List Archive : http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/