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

Re: [microblaze-uclinux] spi and spidev usage



Hi everyone,

There are three different parts to my email.

First, I finally got my SPI device working!  I want to thank Carsten for providing me with the final bit of debug help that helped me find the issue.

I removed my SPI DAC and concentrated solely on my SPI that was mapped to three pins, which are easier to debug the SCLK, MOSI, and SS lines using a scope.

Based on Carsten's advice, I took a copy of my Petalinux reference design, stripped out the software needed to run linux but kept the hardware.  That way, I could test the hardware to make sure it was set up correctly without having to always redo the kernel image and upload it to my board. 

Doing this, I found that I was missing a CLK and RST signal on my SPI module.  I missed these because my connection filter in EDK wasn't set to show all connection.  After fixing this and testing it with my code with petalinux, I made the same change in the Petalinux reference design and tried booting Petalinux.

Success!  I got nothing at first again (SCLK low and SS/MOSI high).  However, using my code that I posted in my last email, my SPI initialized correctly and I could see the clock, data, and SS on the scope!  I switched the constants in my code shown with those in linux/autoconf.h.


Second, my next issue is the DAC.  It refuses to turn on, even in my reference design that doesn't use Petalinux software, so it must be a hardware problem.  Does anybody have experience with contention issues with SPI?  I noticed that I need to disable the flash PROM on my Spartan 3E when trying to access the DAC.  That didn't seem to help.  I also added the DAC CLR pin and tied it to ground, but that usually causes PAR to fail.  Either way, I'm guessing I can't be disabling the flash when using Petalinux, since u-boot needs it.


My third question is for Dr. Williams.  I found a document on creating a custom uCLinux design in the EDK here:

http://www.itee.uq.edu.au/~wu/downloads/uClinux_ready_Microblaze_design.pdf

Is there an updated version of this?  I figured I try to make a custom design since I seem to be having timing and PAR issues when I simply add the DAC CLR pin.

Thanks everyone for all the help.

Matt



On Thu, Apr 2, 2009 at 22:55, Matt Staniszewski <matt.staniszewski@xxxxxxxxx> wrote:
>
> 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