Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Message

Re: SPI Interrupt not firing?

2005-10-12 by ee_gary

--- 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

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.