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

Re: [microblaze-uclinux] spi and spidev usage



Hi Carsten,

I came up with another way to test out my hardware, since that seems to be where the issue is coming from.  Instead of using the _example.c  file, I found a lab project that I built for this board that uses SPI. 

I took the reference design I'm using for Petalinux, gutted the software project portion, but left the hardware intact.  I then added in my software project from the other working design.  This way, I could test my Petalinux hardware setup against a known working set of code. 

I started with the DAC first.  I noticed right away that I didn't have all the filters turned on for my port System Assembly View.  I didn't have a OPB_Clk specified for my two OPB SPI devices, so I hooked those into sys_clk_s.  That was a major find.  However, I couldn't get the DAC to output with my code.  I recieved a lot of errors regarding port conflicts with the FLASH and SDRAM components in the design, so I imagine that there's something shared between the DAC and those devices that might be causing the DAC to not work.

I switched to the 3 header pins that I specified for the second SPI interface.  After adding delays between the SS lines and MOSI lines in my code, I can see the SS line going low and high!  I'm going to scope the SCK and MOSI lines to see if those are working properly as well.

So, I think the missing clk line may fix my Petalinux build as well. 

However, now that I look at my code, could I use my code instead of building a new program using xspi.h functions as my Petalinux user application?  My code uses the BASEADDR values for each of the SPI registers and I declare each register as a volatile so that I can write directly to the memory.  Here are some of my variables and functions:

#define    SPICR        (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x60))
#define    SPISR        (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x64))
#define    SPIDTR    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x68))
#define    SPIDRR    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x6C))
#define    SPISSR    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x70))
#define    SPIGIE    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x1C))
#define    SPIISR    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x20))
#define    SPIIER    (*(volatile unsigned long *)(XPAR_OPB_SPI_0_BASEADDR+0x28))

#define    SPI_DAC    0x01
#define    SPI_AMP    0x02
#define    SPI_ADC    0x04

#define DAC_A 0x00
#define DAC_B 0x01
#define DAC_C 0x02
#define DAC_D 0x03
#define DAC_ALL 0x0F

#define    sendDAC(n,val)        writeSPI(SPI_DAC, 0x00300000 | (((n)&0x0F)<<16) | (((val)&0x0FFF)<<4), 4)
#define    sendAmp(a,b)        writeSPI(SPI_AMP, (((b)&0x07)<<4) | ((a)&0x07), 1)
#define  readADC()           readSPI(2)

void initSPI(void);
void clearSPI(void);
int readSPI(unsigned int numBytes);
void writeSPI(unsigned int device, unsigned int value, unsigned int numBytes);

...

void
initSPI(void)
{
    int i;
    SPISSR=~0;                                            // All Slave Select lines high

    SPICR=0x086;                                        // Setup SPI control
   
    SPIGIE=~0;                                            // Enable SPI Interrupts but no specific ones

    deviceMask=SPISSR;                                // Setup device mask = state when all SS lines are high
       
    SIE=XPAR_OPB_SPI_0_IP2INTC_IRPT_MASK;        // Enable Interrupt in Intc
}


...

void
writeSPI(unsigned int device, unsigned int value, unsigned int numBytes)
{
    int i;
   
    if(numBytes>4)                                        // Maximum send width
        numBytes=4;
       
    while(SPISSR!=deviceMask);                        // Must wait for last transaction to finish
       
    SPISSR&=~device;                                    // Lower SS line for device
       
    for(; numBytes; --numBytes)                    // Put bytes into Tx FIFO MSB first
    {   
        SPIDTR=(value>>((numBytes-1)*8))&0xFF;
    }
    for(;;)
    {
        if(SPISR & 0x04)
            break;
    }
    SPISSR=~0;                                        // Raise SS lines
}

For some reason I feel that it's been written before on this mailing list that you shouldn't use BASEADDR entries in your user applications for Petalinux, but I can't remember.

Thanks.

Matt