Interrupt response time

11 Mar 2010

Hi,

I want to be able to measure very short delays, in the range,say, from 50 nsecs to 5 microsecs.

To start, with I used GPIO as interrupts - as  in the following code with an external pulse source connected to p16.

while(1){

       while(LPC_GPIOINT->IntStatus==0);
           LPC_GPIO2->FIOSET = TEST_1;          
       if(LPC_GPIOINT->IO0IntStatR & (1 << 24)) {
//           LPC_GPIO2->FIOSET = TEST_1;          
           LPC_GPIOINT->IO0IntClr |= (1<<24);
           LPC_GPIO2->FIOCLR = TEST_1;           
 }

The delay in reaching the first FIOSET from the rising edge of the input pulse is around 260 ns, from this line to the second FIOSET is another 260 ns and another 580 ns until the FIOCLR line completes. Running back-to-back FIOSET/FIOCLR shows about 10 nsecs so the device certainly runs fast enough.

These times are much slower than I expected so I guess I should really be using the external interrupt pins EINT0- EINT3 but these don't seem to accessible on the mbed?

EINT1 and EINT2 don't seem to be connected anywhere in the mbed schematic. Is this correct? Maybe I could attach a fine wire???

Thanks for any help.

John.

 

11 Mar 2010 . Edited: 11 Mar 2010

Not sure if this is the issue, but try using an actual interrupt handler instead of polling. It seems you need to use EINT3 vector to handle them. Just declare your handler like this:

extern "C" void EINT3_IRQHandler()
{
// handle interrupt
}

Also, can you show us how you configure GPIOs?

BTW, you can use just = instead of |= when writing to IO0IntClr, it ignores any 0 bits.

11 Mar 2010

Hi Igor,

Thanks for the reply.

Are the EINT pins actually accessible on the mbed board? I would need two as I have separate external start and stop signals.

The test port  is written with LPC_GPIO2->FIOSET = TEST_1;

where TEST_1 is defined as #define TEST_1 (1<<5)

John.

11 Mar 2010

Sorry, I was unclear. I mean that EINT3 vector is also used for GPIO interrupts (UM: "GPIO0 and GPIO2 interrupts share the same position in the NVIC with External Interrupt 3.").

You might have to enable the interrupt in the NVIC for the handler to work:

NVIC_EnableIRQ(EINT3_IRQn);

11 Mar 2010

Thanks for the pointer.

Would using the handler be any faster?

At the moment, a major delay is the time needed for the line

      while(LPC_GPIOINT->IntStatus==0);

to execute.

One channel of the logic analyser is connected to the input pin on the card, the second channel is on the line

LPC_GPIO2->FIOSET = TEST_1;

 

11 Mar 2010

Thanks for the pointer.

Would using the handler be any faster?

At the moment, a major delay is the time needed for the line

      while(LPC_GPIOINT->IntStatus==0);

to execute.

One channel of the logic analyser is connected to the input pin on the card, the second channel is on the line

LPC_GPIO2->FIOSET = TEST_1;

 

11 Mar 2010

Sorry for the above posts - my mouse must have jumped. So once again

Thanks for the pointer.

Would using the NVIC handler be any faster?

At the moment, a major delay is the time needed for the line

      while(LPC_GPIOINT->IntStatus==0);

to execute.

One channel of the logic analyser is connected to the input pin on the card, the second channel looks at the IO port corresponding to the line following "while(LPC_GPIOINT->IntStatus==0);", ie

LPC_GPIO2->FIOSET = TEST_1;

The measured delay is anywhere from 200 to 400 nsecs. The overhead of the while loop code can't be more than a few instructions, so I am puzzled as to why reading the LPC_GPIOINT->IntStatus register seems to take so long?

John..

 

 

11 Mar 2010

I am not sure whether it will be faster. On the one hand, the handler will execute only on detecting the rising edge (assuming you configured the pin so) instead of doing useless check all the time. On the other hand, the processor will have to fetch the interrupt vector and stack a couple of registers before it gets to the handler body. It will only be a couple of clock cycles, but still.

BTW, another thing you could try is to put __WFI() in the loop body:

while(LPC_GPIOINT->IntStatus==0) __WFI();

This will make the processor stop, and continue only after it receives an interrupt (any interrupt, not necessarily GPIO). I'm not sure whether it will actually improve response time.

11 Mar 2010

For what it's worth, here's the assembly generated for your loop (with my comments):

                LDR     R0, =0x40028000 ; R0 = LPC_GPIOINT_BASE
                LDR     R2, =0x2009C000 ; R2 = LPC_GPIO_BASE
                MOVS    R1, #0x20
loop_wait
                LDR.W   R3, [R0,#0x80]  ; R3 = IntStatus (0x40028080)
                CMP     R3, #0          ; R3 = 0?
                BEQ     loop_wait       ;    if yes, continue looping
                STR     R1, [R2,#0x58]  ; FIO2SET (0x2009C058) = 0x20
                LDR.W   R3, [R0,#0x84]  ; R3 = IO0IntStatR (0x40028084)
                TST.W   R3, #0x1000000  ; R3 & (1<<24)
                BEQ     loop_wait       ;   if 0, continue looping
                LDR.W   R3, [R0,#0x8C]  ; R3 = IO0IntClr (0x4002808C)
                ORR.W   R3, R3, #0x1000000 ; R3 |= 1<<24
                STR.W   R3, [R0,#0x8C]  ; IO0IntClr (0x4002808C) = R3
                STR     R1, [R2,#0x5C]  ; FIO2CLR (0x2009C05C) = 0x20
                B       loop_wait

11 Mar 2010

Thanks again for your patience.

Looking at the circuit and the board itself, it does seem possible to connect a pair of wires to pins 51 and 52, then enable EINT1 and EINT2 as the interrupt sources.

Are there any other connections to these pins that are not shown on the schematic.

John.

11 Mar 2010

Thanks for the code sample, most helpful but I _really_ now don't understand the delay  because the first loop block surely should execute in two or three clocks and then set the port high?

The second BEQ should probably refer to a second and different label after the FIO2SET line?

 

11 Mar 2010

It's actually supposed to jump to after the if, but since that's the end of the while(1) loop, the compiler decided to jump directly to the start of the loop again (you didn't say if there's any code after the if so I closed the while(1) ).

And yes, I agree that it looks like the code should be fast enough. So I guess we'll have to see if someone from mbed team has any more ideas.

11 Mar 2010

It is almost as if the interrupts are being clocked before being read by the LPC_GPIOINT->IntStatus line and the clock (if it exists) would necessarily be asynchronous with the input signal transitions??

I do hope that the mbed team has some ideas for me to try.

John.