EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

SPI Setup

Started by dasoberdick February 12, 2010
Hello,

I am trying to set up the SPI on the AT91SAM7S265K. I don't seem to be getting any output on the MOSI or the SCK. Anyone seeing any problems with my setup? All I am doing is calling the setup function and then trying to send a 'U' out. Here is my initialization and send functions.

#include "AT91SAM7S256.h"
#include "binary.h"
#include "spi.h"
#include "project.h"

void spi_init()
{
volatile AT91PS_SPI pSPI = AT91C_BASE_SPI; // Pointer to SPI data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // Pointer to PMC data structure
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // Pointer to PIO data structure

pSPI->SPI_CR = AT91C_SPI_SWRST; // software reset (there is a function to do this, you should test it out)
pPMC->PMC_PCER = (1<<5); // enable SPI peripheral clock SPI peripheral ID is 5 (a function to do this too)

//AT91C_BASE_PIOA->PIO_PPUDR = BIT11 | BIT12 | BIT13 | BIT14; //disable pullup on input
// All I/O lines are inputs with the pullup enabled at rest (burn that into memory)
AT91C_BASE_PIOA->PIO_OER = BIT13 | BIT14; //BIT13=MOSI=output, BIT14=SPICLK=output
pPIO->PIO_PDR = BIT12 | BIT13 | BIT14; //Set PIO to NOT use the SPI pins. PA12_MISO PA13_MOSI PA14_SPCK
pPIO->PIO_ASR = BIT12 | BIT13 | BIT14; //Set Alternate PIO A for SPI pins.

// Setup mode register
pSPI->SPI_MR = AT91C_SPI_MSTR // Enable master mode
| AT91C_SPI_PS_VARIABLE // Watch out for this... We want the features but we arnt using the pins...
| AT91C_SPI_MODFDIS; // Disable mode fault detection

pSPI->SPI_IDR = 0x3FF; // All interupts are off

// Setup Chip Select Register for flash memory
pSPI->SPI_CSR[0] = AT91C_SPI_NCPHA // SPI Bus Protocol Mode 0 (The AT26F004 supports modes 0 and 3)
| AT91C_SPI_BITS_8 // 8 bit data transfers
| ((2<<8) & AT91C_SPI_SCBR) // Baud Rate = MCK/SCBR = 24MHz (The AT26F004 supports a maximum of 33MHz)
| ((6<<16) & AT91C_SPI_DLYBS) // Dont know about this one,
| ((6<<24) & AT91C_SPI_DLYBCT); // or this one yet...

//Control Register : Enable SPI
pSPI->SPI_CR = AT91C_SPI_SPIEN;
}

void spi_cleanup()
{

}

void spi_send(unsigned char ss_num, unsigned int data)
{
volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;
while(!(pSPI->SPI_SR & (AT91C_SPI_TDRE))); //wait for a clear transmit register
pSPI->SPI_TDR = ((data & 0xFFFF) | (ss_num<<16)); //assign the transmit register plus the chip select
}

unsigned char spi_transfer(unsigned char ss_num, unsigned int data)
{
int address = ~(1< volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;

while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY)));//wait for transfer to complete
volatile unsigned int discard = pSPI->SPI_RDR; //clear the read register
pSPI->SPI_TDR = ((data & 0xFFFF) | ((address<<16) & AT91C_SPI_TPCS)); //assign the data plus the chip select
while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY))); //wait for transfer to complete
while(!(pSPI->SPI_SR & AT91C_SPI_RDRF)); //make sure there's a read value
return((unsigned char)(pSPI->SPI_RDR)); //return read value
}

On Fri, Feb 12, 2010 at 3:01 PM, dasoberdick wrote:

> // All I/O lines are inputs with the pullup enabled at rest (burn that into
> memory)
>
> AT91C_BASE_PIOA->PIO_OER = BIT13 | BIT14; //BIT13=MOSI=output,
> BIT14=SPICLK=output
> pPIO->PIO_PDR = BIT12 | BIT13 | BIT14; //Set PIO to NOT use the SPI pins.
> PA12_MISO PA13_MOSI PA14_SPCK
> pPIO->PIO_ASR = BIT12 | BIT13 | BIT14; //Set Alternate PIO A for SPI pins.
>
What happens if you add BIT11, NPCS0, to the above. Since your transfer
functions are expected to react to chip select settings, you may need at
least CS0 to be available to the peripheral.

> // Setup mode register
> pSPI->SPI_MR = AT91C_SPI_MSTR // Enable master mode
> | AT91C_SPI_PS_VARIABLE // Watch out for this... We want the features but
> we arnt using the pins...
>
This implementation can probably get by with fixed mode addressing because,
especially if you only be connecting to one peripheral. In that case, you
can just set PCS in SPI_MR once and be done with it. This isn't the reason
why your transfer isn't working though.

> void spi_send(unsigned char ss_num, unsigned int data)
> {
> volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;
> while(!(pSPI->SPI_SR & (AT91C_SPI_TDRE))); //wait for a clear transmit
> register
> pSPI->SPI_TDR = ((data & 0xFFFF) | (ss_num<<16)); //assign the transmit
> register plus the chip select
> }
>
> unsigned char spi_transfer(unsigned char ss_num, unsigned int data)
> {
> int address = ~(1< > volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;
>
> while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY)));//wait for transfer to
> complete
> volatile unsigned int discard = pSPI->SPI_RDR; //clear the read register
> pSPI->SPI_TDR = ((data & 0xFFFF) | ((address<<16) & AT91C_SPI_TPCS));
> //assign the data plus the chip select
> while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY))); //wait for transfer to
> complete
> while(!(pSPI->SPI_SR & AT91C_SPI_RDRF)); //make sure there's a read value
> return((unsigned char)(pSPI->SPI_RDR)); //return read value
> }
>
Nothing jumps out at me here. Do neither of these functions get stuck
inside one of the while loops?

Regards,
Ken
The problem is the given hardware does have multiple slaves. It just uses gpio as chip selects. That made me think hard about fixed vs variable. I will try your suggestion tomorrow. Thanks.
--- In A..., Ken Smith wrote:
>
> On Fri, Feb 12, 2010 at 3:01 PM, dasoberdick wrote:
>
> > // All I/O lines are inputs with the pullup enabled at rest (burn that into
> > memory)
> >
> > AT91C_BASE_PIOA->PIO_OER = BIT13 | BIT14; //BIT13=MOSI=output,
> > BIT14=SPICLK=output
> > pPIO->PIO_PDR = BIT12 | BIT13 | BIT14; //Set PIO to NOT use the SPI pins.
> > PA12_MISO PA13_MOSI PA14_SPCK
> > pPIO->PIO_ASR = BIT12 | BIT13 | BIT14; //Set Alternate PIO A for SPI pins.
> >
> What happens if you add BIT11, NPCS0, to the above. Since your transfer
> functions are expected to react to chip select settings, you may need at
> least CS0 to be available to the peripheral.
>
> > // Setup mode register
> > pSPI->SPI_MR = AT91C_SPI_MSTR // Enable master mode
> > | AT91C_SPI_PS_VARIABLE // Watch out for this... We want the features but
> > we arnt using the pins...
> >
> This implementation can probably get by with fixed mode addressing because,
> especially if you only be connecting to one peripheral. In that case, you
> can just set PCS in SPI_MR once and be done with it. This isn't the reason
> why your transfer isn't working though.
>
> > void spi_send(unsigned char ss_num, unsigned int data)
> > {
> > volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;
> > while(!(pSPI->SPI_SR & (AT91C_SPI_TDRE))); //wait for a clear transmit
> > register
> > pSPI->SPI_TDR = ((data & 0xFFFF) | (ss_num<<16)); //assign the transmit
> > register plus the chip select
> > }
> >
> > unsigned char spi_transfer(unsigned char ss_num, unsigned int data)
> > {
> > int address = ~(1< > > volatile AT91PS_SPI pSPI = AT91C_BASE_SPI;
> >
> > while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY)));//wait for transfer to
> > complete
> > volatile unsigned int discard = pSPI->SPI_RDR; //clear the read register
> > pSPI->SPI_TDR = ((data & 0xFFFF) | ((address<<16) & AT91C_SPI_TPCS));
> > //assign the data plus the chip select
> > while((pSPI->SPI_SR & !(AT91C_SPI_TXEMPTY))); //wait for transfer to
> > complete
> > while(!(pSPI->SPI_SR & AT91C_SPI_RDRF)); //make sure there's a read value
> > return((unsigned char)(pSPI->SPI_RDR)); //return read value
> > }
> >
> Nothing jumps out at me here. Do neither of these functions get stuck
> inside one of the while loops?
>
> Regards,
> Ken
>


The 2024 Embedded Online Conference