I'm a newbie, so don't take my comment too seriously, but... why are
you disabling SPIE interrupts in your enqueue function? Couldn't this
adversedly affect the expected behavior? If your intention is to
protect the buffer pointers while these are being updated, I'd go for
a full IRQ disable rather than a targeted masking; of course this is
acceptable only if you can afford a small lag between interrupts.
Also, as I read the pseudo-code example in the LPC2138 user's manual,
the SPI control register should be written to before writing onto the
data register (which in some way may suggest that it should not be
written to after the data is set in the shift register). Yhis is what
I'd do:
int spi0Putch(int ch)
{
uint16_t temp;
unsigned cpsr;
cpsr = disableIRQ(); // disable global interrupts before atempting to
read spi0_tx_insert_idx (in case of multitasking being used)
// Avoid using modulo operator in ARM7 for performance reasons
//temp = (spi0_tx_insert_idx + 1) % SPI0_TX_BUFFER_SIZE;
temp = spi0_tx_insert_idx + 1;
if( temp == SPI0_TX_BUFFER_SIZE ) temp = 0;
if (temp == spi0_tx_extract_idx)
{
restoreIRQ(cpsr); // restore global interrupts
return -1; // no room
}
// check if in process of sending data
if (spi0_tx_running){
// add to queue
spi0_tx_buffer[spi0_tx_insert_idx] = (uint8_t)ch;
spi0_tx_insert_idx = temp;
}
else{
// set running flag and write to output register
S0SPCR |= SPCR_SPIE; // enable TX interrupts before writing to
SOSPDR
spi0_tx_running = 1;
S0SPDR = (uint8_t)ch;
}
restoreIRQ(cpsr); // restore global interrupts
return (uint8_t)ch;
}
Hope this helps.
Guille
--- In lpc2000@yahoogroups.com, "ee_gary" <ee_gary@y...> wrote:
>
> --- In lpc2000@yahoogroups.com, Sten <list@n...> wrote:
> >
> > ee_gary wrote:
> > > Long time lurker, first time poster...
> > >
> > > I've set the SPIE bit in the Control Register. I can see the
SPIF bit
> > > get set in the Status Register. However, I do NOT see the SPI
> > > Interrupt bit get set in the Interrupt Register. Shouldn't
this occur
> > > as soon as the SPIF bit is set, regardless of how the VIC is
set up?
> > > I have the VIC set up "correctly", but the ISR never executes
> > > (presumably because the SPI Interrupt never fires). I've had
> > > interrupts working correctly for UART0 and a timer, so I know
that
> > > interrupts can work (they just aren't in this occasion).
> > >
> > > I can do non-interrupt SPI transmits (i.e. the 1st byte of an
> > > interrupt-based multibye transfer) so I know the hardware is ok
(SSEL
> > > = 1). I've duplicated this on the MCB2130 and a LPC2214 dev
board.
> > >
> > > Any insight from those that have implemented interrupt based
SPI is
> > > appreciated.
> > >
> > > Stumped in Seattle...
> > >
> >
> > Please can you send a small portion of source code? It sounds
> unbelievable.
> >
> > Sten
> >
> > --
> > /************************************************
> > Do you need a tiny and efficient real time
> > operating system (RTOS) with a preemtive
> > multitasking for LPC2000 or AT91SAM7?
> >
> > http://nanortos.net-attack.de/
> >
> > Or some open-source tools and code for LPC2000?
> >
> > http://www.net-attack.de/
> >
> > ************************************************/
> >
>
> It'd be my pleasure. Here's the init function:
> void spi0Init(void)
> {
> // Set port pins for SPI0
> PINSEL0 = (PINSEL0 & ~S0_PINMASK) | S0_PINSEL;
>
> // Set SPI Registers
> S0SPCR = 0; // Clear all bits
> S0SPCR |= SPCR_CPHA; // Data sampled on rising edge
> S0SPCR |= SPCR_CPOL; // SCK active low
> S0SPCR |= SPCR_MSTR; // Master mode
>
> S0SPSR; // Cleared by a read of this register
> S0SPDR; // Cleared by a read of this register
> S0SPCCR = 128; // 8 is max speed
> S0SPINT = 1; // Cleared by writing a 1 to it
>
> // initialize the interrupt vector
> VICIntSelect = 0; // Select IRQ
> VICIntEnable = 0x00000400;
> VICVectAddr0 = (unsigned long)spi0ISR;
> VICVectCntl0 = 0x0000002A;
>
> // initialize the transmit data queue
> spi0_tx_extract_idx = spi0_tx_insert_idx = 0;
> spi0_tx_running = 0;
> }
>
> and the transmit function:
> int spi0Putch(int ch)
> {
> uint16_t temp;
> unsigned cpsr;
>
> temp = (spi0_tx_insert_idx + 1) % SPI0_TX_BUFFER_SIZE;
>
> if (temp == spi0_tx_extract_idx)
> return -1; // no room
>
> cpsr = disableIRQ(); // disable global interrupts
> S0SPCR &= ~SPCR_SPIE; // disable TX interrupts
> restoreIRQ(cpsr); // restore global interrupts
>
> // check if in process of sending data
> if (spi0_tx_running){
> // add to queue
> spi0_tx_buffer[spi0_tx_insert_idx] = (uint8_t)ch;
> spi0_tx_insert_idx = temp;
> }
> else{
> // set running flag and write to output register
> spi0_tx_running = 1;
> S0SPDR = (uint8_t)ch;
> }
> cpsr = disableIRQ(); // disable global interrupts
> S0SPCR |= SPCR_SPIE; // enable TX interrupts
> restoreIRQ(cpsr); // restore global interrupts
>
> return (uint8_t)ch;
> }
>
> and finally, the ISR that never fires...
> void spi0ISR(void)
> {
> // perform proper ISR entry so thumb-interwork works properly
> ISR_ENTRY();
>
> // check if more data to send
> if (spi0_tx_insert_idx != spi0_tx_extract_idx){
> S0SPDR = spi0_tx_buffer[spi0_tx_extract_idx++];
> spi0_tx_extract_idx %= SPI0_TX_BUFFER_SIZE;
> }
> else{ // No more to transmit
> S0SPCR &= ~SPCR_SPIE;
> spi0_tx_running = 0;
> }
>
> S0SPINT = 1;
> VICVectAddr = 0x00000000;
>
> ISR_EXIT();
> }
>
> It seems like it should be something simple. Everything looks okay,
> but the ISR never fires.
>
> Thanks,
>
> Gary
>Message
Re: SPI Interrupt not firing?
2005-10-17 by Guillermo Prandi
Attachments
- No local attachments were found for this message.