SPI Slave with Interrupt

06 Jul 2012

Hello,

I'm trying to configure a SPI Slave module with a interrupt on receive. I saw it's a common topic here but I couldn't find any answere to help me.

My code is really simple, I'm using a SPI master to generate signal to a SPI Slave. I put a LED to turn on when the SPI Slave receve something. If I do it, I can complete the rest. The code is:

DigitalOut ledDbg( LED4 ) ;

extern "C" static void execute_spi_slave_hw( void ) { ledDbg = 1; }

The object is a global variable created with this line:

SPISlave dev_spi_slave( MOD_SPI_SLAVE_MOSI, MOD_SPI_SLAVE_MISO , MOD_SPI_SLAVE_SCK , MOD_SPI_SLAVE_SS ) ;

And the configuration of SPI Slave Interrupt is:

dev_spi_slave.format( 8 , 0 ) ; NVIC_SetVector( SPI_IRQn , ( uint32_t ) execute_spi_slave_hw ) ; NVIC_SetPriority( SPI_IRQn , 2 ) ; NVIC_EnableIRQ( SSP1_IRQn ) ; dev_spi_slave.reply( ( int ) 0x3C ) ;

I know that I have data because my SPI Master receive the 0x3C, but the interrupt function never run. What I'm doing wrong?

Thanks everyone.

06 Jul 2012

With code tags:

DigitalOut ledDbg( LED4 ) ;

extern "C" static void execute_spi_slave_hw( void )
{
    ledDbg = 1;
}

The object is a global variable created with this line:

SPISlave dev_spi_slave( MOD_SPI_SLAVE_MOSI, MOD_SPI_SLAVE_MISO , MOD_SPI_SLAVE_SCK , MOD_SPI_SLAVE_SS ) ;

And the configuration of SPI Slave Interrupt is:

dev_spi_slave.format( 8 , 0 ) ;
NVIC_SetVector( SPI_IRQn , ( uint32_t ) execute_spi_slave_hw ) ;
NVIC_SetPriority( SPI_IRQn , 2 ) ;
NVIC_EnableIRQ( SSP1_IRQn ) ;
dev_spi_slave.reply( ( int ) 0x3C ) ;

First thing I notice is that you enable a different IRQ than the one you set, so I guess that is a typo and already will cause a problem.

Next if I read the LPC1768 user guide it says a bit needs to be set to generate interrupts. Now I dont know if it will be set on default by the mbed function, but since it should not actually use it, I doubt it. It is described on page 407 of the manual http://www.nxp.com/documents/user_manual/UM10360.pdf, so you can manually set it. But I do not know if mbed functions will clear it. So best chance is to set it completely at the end (after slave.reply).

06 Jul 2012

Hello Erik,

You were right, I was setting the interrupt wrong. Thanks. But unfortunately it still doesn't work.

I saw the document that you said and I tried to configure the SPI Slave by this way. The code is:

LPC_SPI->SPCR   = 0x00000000 ; // SPI Slave, 8 bits, CPHA = 0, CPOL = 0.
LPC_SPI->SPCR  |=  ( 1 << SPIE ) ; // Set up the interrupt control register
LPC_SPI->SPINT &= ~( 1 << SPIF ) ; // clear interrupt flag

NVIC_SetVector( SPI_IRQn , ( uint32_t ) executa_spi_slave_hw ) ;
NVIC_SetPriority( SPI_IRQn , 2 ) ;
NVIC_EnableIRQ( SPI_IRQn ) ;

dev_spi_slave.reply( ( int ) 0x3C ) ;

I checked again the IO pins of the device I'm using (could it be SSP0 SSP1 rather than SPI), but I think it's correct.

#define MOD_SPI_SLAVE_MOSI             p11
#define MOD_SPI_SLAVE_MISO             p12
#define MOD_SPI_SLAVE_SCK              p13
#define MOD_SPI_SLAVE_SS               p14

SPISlave dev_spi_slave( MOD_SPI_SLAVE_MOSI, MOD_SPI_SLAVE_MISO , MOD_SPI_SLAVE_SCK , MOD_SPI_SLAVE_SS ) ;

Can you see something wrong this time? Thank you again.

Francesco

06 Jul 2012

LPC_SPI->SPCR   = 0x00000000 ; // SPI Slave, 8 bits, CPHA = 0, CPOL = 0.
LPC_SPI->SPCR  |=  ( 1 << SPIE ) ; // Set up the interrupt control register
LPC_SPI->SPINT &= ~( 1 << SPIF ) ; // clear interrupt flag

First line is taken care of by the mbed library, this will in theory only overwrite the settings made by the library, but since you call the slave.reply afterwards it will set it back to what it wants. Second one is the one I think you need, third one can be useful, but only if you get false interrupts when you enable it.

I would try setting your second line after you call slave.reply. The mbed function will put its own settings in the SPI registers, overwriting your changes. Now I simply do not know what it will do with the interrupt enable bit, but possibly it will clear that also. So I would try setting the bit after you call the slave.reply function.

Besides that I don't see any obvious problems. You can try to do some error checking by printing the value of status flags to your serial PC connection.

If it indeed uses the SSP interfaces (good possibility if I quickly read user guide, but havent yet looked into SPI hardware myself yet), you should find out fairly quickly by printing some status flags of SSP/SPI registers to your PC.

06 Jul 2012

Dear Erik,

Thanks for your help. I add more specific code and it works. Not very well, but my LED turn on.

I change that lines for this ones:

LPC_SC->PCONP           |=  (1 << PCSPI);    // pedantic, should already be powered up
LPC_SC->PCLKSEL0        &= ~(3 << PCLK_SPI); // reset clock select bits PCLK = CCLK
LPC_PINCON->PINSEL0     |=  ( unsigned int ) (3 << 30);       // set up SCK in PINSEL0
LPC_PINCON->PINSEL1     |=  (3 << 0);        // set up SSEL in PINSEL1
LPC_PINCON->PINSEL1     |=  (3 << 2);        // set up MISO in PINSEL1
LPC_PINCON->PINSEL1     |=  (3 << 4);        // set up MOSI in PINSEL1
LPC_SPI->SPCR            = (1 << SPIE);      // set up control register
junk                     = LPC_SPI->SPSR;    // clear status register
junk                     = LPC_SPI->SPDR;    // clear data register
LPC_SPI->SPDR            = 0x00;             // initial return value
LPC_SPI->SPINT           = (1 << SPIF);      // clear interrupt flag

I agree with you, probably it's a better work just with the register, without the lib SPISlave. Thank you.

Francesco

12 Jan 2015

Francesco,

What did you mean by:

Quote:

I add more specific code and it works. Not very well, but my LED turn on.

How does it work but not very well?

Thanks! -Brad