This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Nested interrupt

Hi

Im using a timer to generate interrupt based on the match registers. On one of those interrupt, I would like to start a SPI data transfer. The SPI transfer is also using vector based interrupt (for sending 3 bytes).
But (of cause) the SPI interrupt doesnt work from within another VIC interrupt, so I guess I have to use nested interrupts??
Im looking at the nested interrupt sample from KEIL.
I guess I have todo the following:

timer_ISR
  IENABLE
  Start SPI transfer
  Do something else
  Ack the interrupt


SPI_ISR
  Send byte1
  Send byte2
  Send byte3
  IDISABLE
  Ack the interrupt


Is this the right approach?

Using af LPC2103 ARM7

/Thomas

  • There is no problem starting an SPI transfer from your interrupt handler - no need for nested interrupts for that.

    Nested interrupts is just if you want one interrupt handler to be able to interrupt another interrupt handler.

    If you need to service the SPI interrupt before leaving the timer interrupt, or if you need to service the timer interrupt before ending the SPI interrupt.

    But both SPI and timer interrupts should normally (as almost all interrupts) be very short and quick, in which case you can run the two interrupts after each other - something the processor will manage by itself.

  • I see...

    But I cant get the SPI interrupt to fire if I start the transfer within my timer interrupt. Is it because I call a function from my timer ISR thats start the SPI transfer? Se code below.

    // Timer ISR
    void tc1ISR(void) __irq // Timer interrupts
    {
      // Check interrupt cause
      if( (T1IR&0x01) == 0x01 )
      {
        // Match register 0
        PINSEL0 &= ~0x00000400;
        IODIR0 &= ~RDY_PIN; // P0.5 defined as input
        // CS low --> starting the converion
        IOCLR0 = 0x00000080;
        VICVectAddr = 0;
        T1IR  |=0x01;
      }
      else if((T1IR&0x02) == 0x02 )
      {
         // Start SPI transfeer... 3 bytes send
         SPI_Read(m_byAnalogData, 3); // <-- This start the SPI transfer
         // Clear interrupt flag
         VICVectAddr = 0;
         T1IR  |=0x02;
      }
    }
    
    // SPI isr never reached if i start the transfere within the timer ISR
    void SPI_Isr(void) __irq
    {
      // Read the SPI status register
      if ((S0SPSR & 0xF8) == 0x80)
      {
         // Switch on state
         switch(bySPIState)
         {
           case 0:
           {
            lConversionData = (S0SPDR);// & 0x3F);
             bySPIState = 1;
           }
           break;
           case 1:
           {
              lConversionData = lConversionData<<8;
              lConversionData |= S0SPDR;
              bySPIState = 2;
           }
           break;
           case 2:
           {
              lConversionData = lConversionData<<8;
              lConversionData |= S0SPDR;
              bySPIState = 0;
           }
           break;
        }
        // Still more data to send?
        if (--count > 0)
        {
           // sent next byte
           S0SPDR = *msg;
        }
        else
        {
           state = SPI_OK; // transfer completed
        }
      }
      // Reset  SPI interrupt flag
      S0SPINT = 0x01;
      // ACK the interrupt
      VICVectAddr = 0;
    }
    

    But if I instead just sets and flag in the timer ISR, and then start the SPI transfer when this flag gets true, the SPI interrupts works fine. But that just take the point away of using IRQ, if I have to poll a flag!!

    /Thomas

  • I just have to add, that the call to SPI_Read is blocking until the 3 bytes are send.
    I guess I cant get the SPI interrupts before the timer ISR has ack'ed the interrupt?

  • If you are going to busy-wait for the SPI transfer, then you should not run the SPI interface with interrupts.

    Instead, you should select the fastest working baudrate and then poll for your results. Interrupts are used when you do not want to poll. If you are going to poll anyway, then it is more efficient to just poll instead of having an interrupt receive the data and other code busy-waiting for the interrupt to report that the transfer is done.

    But the question is: Why do one interrupt handler need to send a number of bytes and then hang, waiting for the result? Why can't the results be stored by the SPI interrupt into a receive buffer and then consumed by a main loop?

  • Hi

    I did just that. I just start the SPI transfere in my timer interrupt. Then when SPI isr is saving the result for future use :-)