We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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!!
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?
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 :-)