[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/