EINT1 and EINT2

18 Mar 2010

I have attached fine wires to pins 51 and 52 and connected them to my dual pulse generator that emits two pulses delayed by a settable interval in the 10s to 100s of nanoseconds.

Initially I set both interrupts for edge-sensitive rising-edge mode and saw nothing in my interrupt handlers.

I changed to level sensitivity and found that I could only get one handler to respond at a time - for instance if I set  LPC_SC->EXTPOLAR = 2 , then  EINT1_IRQHandler() responded OK, and if I put LPC_SC->EXTPOLAR = 4 , then  EINT2_IRQHandler()  responded OK.

So my wiring is OK.

But if I set LPC_SC->EXTPOLAR = 6 expecting both interrupts to fire, one delayed from the other, only the EINT1_IRQHandler() gets fired. The delay between the pulses for these test was about 500ns.

Any help or pointers would be very gratefully appreciated.

John Robbins.

18 Mar 2010

Do you clear the interrupt in the handler? That might explain why the second one is not triggered.

You might also be forgetting some initialization. Here's how it's done in the sample from NXP:

/* LED pin in byte style on P1 */
#define POLL_LED    (1<<4)      // P1.28
#define INT0_LED    (1<<5)      // P1.29
#define INT3_LED    (1<<7)      // P1.31
#define LED2_MASK   ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6))
#define LED1_MASK   (POLL_LED | (INT0_LED) | (INT3_LED))

/**
 * @brief Delay function
 */
void delay (void) {
  unsigned int i;

  for (i = 0; i < 0x100000; i++) {
  }
}



/**
 * @brief External Interrupt 0 Handler
 */
void EINT0_IRQHandler(void)
{
          int i;
          SC->EXTINT |= 0x1;  //clear the EINT0 flag
          for (i= 0; i<10; i++)
          {
            FIO_ByteSetValue(1, 3, INT0_LED);
            delay();
            FIO_ByteClearValue(1, 3, INT0_LED);
            delay();
          }
}



/**
 * @brief External Interrupt 3 Handler
 */
void EINT3_IRQHandler(void)
{
          int j;
          if (GPIOINT->IO0IntStatF == 0x02000000)
          {
              GPIOINT->IO0IntClr = 0x02000000;
              for (j= 0; j<10; j++)
              {
                    FIO_ByteSetValue(1, 3, INT3_LED);
                    delay();
                    FIO_ByteClearValue(1, 3, INT3_LED);
                    delay();
              }
          }
}

// Main Program
int main (void)
{
    PINSEL_CFG_Type PinCfg;

    SystemInit();

    //  Set Vector table offset value
#if (__RAM_MODE__==1)
    NVIC_SetVTOR(0x10000000);
#else
    NVIC_SetVTOR(0x00000000);
#endif

    //p1.31 , P1.29 and P1.28 are outputs
    FIO_ByteSetDir(1, 3, LED1_MASK, 1);
    FIO_ByteSetDir(2, 0, LED2_MASK, 1);
    // Turn off all LEDs
    FIO_ByteClearValue(1, 3, LED1_MASK);
    FIO_ByteClearValue(2, 0, LED2_MASK);


    //Initialize EXT registers
    SC->EXTINT = 0x0;
    SC->EXTMODE = 0x0;
    SC->EXTPOLAR = 0x0;

    /* edge sensitive */
    SC->EXTMODE = 0xF;
    /* falling-edge sensitive */
    SC->EXTPOLAR = 0x0;
    /* External Interrupt Flag cleared*/
    SC->EXTINT = 0xF;

    /* P2.10 as /EINT0 */
    PinCfg.Funcnum = 1;
    PinCfg.OpenDrain = 0;
    PinCfg.Pinmode = 0;
    PinCfg.Pinnum = 10;
    PinCfg.Portnum = 2;
    PINSEL_ConfigPin(&PinCfg);

    // Enable GPIO interrupt  P0.25/AD0.2
    GPIOINT->IO0IntEnF  = 0x02000000;

    NVIC_SetPriorityGrouping(4);  //sets PRIGROUP to 3:2 (XXX:YY)
    NVIC_SetPriority(EINT0_IRQn, 0);   //000:00 (bit 7:3) assign eint0 to group 0, sub-priority 0 within group 0
    NVIC_SetPriority(EINT3_IRQn, 4);   //001:00 (bit 7:3) assign GPIO int to group 1, sub-priority 0 within group 1


    NVIC_EnableIRQ(EINT0_IRQn);
    NVIC_EnableIRQ(EINT3_IRQn);

    while (1)
    {
        FIO_ByteSetValue(1, 3, POLL_LED);
        delay();
        FIO_ByteClearValue(1, 3, POLL_LED);
        delay();
    }
}


18 Mar 2010

Thanks for the code sample - I will try it shortly.

In Yiu's book, The Definitive Guide to the Arm Cortex-M3, on page 169, there is a sentence that seems to imply that in the M3 it is not necessary to deassert the interrupt in the handler. I was going to try that but I will use your code sample first.

John.

18 Mar 2010

Hi,

I am just about ready to give up on trying to use the external interrupt inputs.

Igor, I was going to use your example but it uses a GPIO interrupt. I had already got a working code using a pair of GPIO interrupts but found that the delays were more than I wanted.

I cut the code back just to use EINT1, tried every combination of EXTINT, EXTMODE and EXTPOLAR. If I set EXTMODE to level, I get continuous multiple interrupts as it seems to trigger repeatedly on the input square waveform, If  use edge-sensitive nothing happens.

I have tried including SystemInit() in main() without any change in performance but I believe the initialisation is anyway done prior to main() being called.

If anybody has a working version of code that uses external interrupts I would be only too happy to try it although I realise that the mbed normally does not have access to these pins.

 

 

18 Mar 2010 . Edited: 18 Mar 2010

Hi John,

Out of interest, are you trying to accurately time a fast pulse or alike with this code?

If so, have you considered using the Timer/Capture blocks of the LPC1768? These allow you to capture a timer value on a pin transition (and cause an interrupt too, e.g. to read what it is). See Chapter 21 of the LPC17xx User Manual for details. For example, CAP2.0 and CAP2.1 are available on p29 and p30:

p29 = P0_5 = CAP2.1
p30 = P0_4 = CAP2.0

Sorry if this is not useful, but it looked like this sort of application.

Simon

18 Mar 2010

Hi Simon,

Thanks for the hint. I had considered the capture inputs earlier. The application is a laser range finder where I have already developed a very fast short-pulse laser driver and now need to measure the time between the outgoing pulse and the return, maybe a maximum difference of 100 - 200 ns. I could use the capture as you suggested with a free-running clock, discarding the data when the clock count rolls over. I am integrating the data over a second or so.

As I posted earlier in another thread, the GPIO interrupts seem to invoke a 500 ns delay and this was unacceptable in my application. Do you think the capture circuits would be faster?

I am still puzzled why I am having so much trouble with the external interrupts - they looked simple enough to set up and use??

John.

23 Mar 2010

Hello,  I am just a few hours into meeting mbed and trying tutorials. It is quite exciting and I am hooked.

 Is there a code for measuring time interval (in hundreds of microseconds)between falling edges of an input pin? I need to distinguish between 1.25 milliseconds and 2.6 milliseconds of a pulse width duration in  PWM system.

How do I access the hardware registers?  How do I set up interrupts and service them? Any help is appreciated.

Thanks,

Victor

23 Mar 2010

 

 

23 Mar 2010

Here is the code I used for delays in the nsecs to microsecs range. I had already posted it a few days ago but cannot find the message.


#include "mbed.h"

DigitalOut led4(LED4);
DigitalOut led3(LED3);
DigitalOut led2(LED2);
DigitalOut led1(LED1);

#define TEST_1 (1<<5)
#define START_PULSE (1 << 24)
#define STOP_PULSE (1 << 25)

volatile int count;
volatile int loop_count;

int main(){

    led4 = 1;
  
    LPC_GPIO2->FIODIR |= TEST_1;
    LPC_GPIOINT->IO0IntEnR =  START_PULSE |  STOP_PULSE;   //1<<24 | 1<<25;

    LPC_SC->PCONP |= 1<<1;    // Timer0 Power On
    LPC_TIM0->PR = 0;        // no prescaler
    LPC_TIM0->CTCR = 0x0;    // default timer mode
    LPC_TIM0->TCR = 0x0;    // disable counter
    count = 0;
    loop_count = 0;

    while(1){
       while(LPC_GPIOINT->IntStatus==0);                   // look for either interrupt, start will be first
           LPC_TIM0->TCR = 0x1;        //start timer
           LPC_GPIO2->FIOSET = TEST_1;
           while((LPC_GPIOINT->IO0IntStatR & STOP_PULSE)==0);  // wait for stop (1 << 25)
           LPC_TIM0->TCR = 0x0;        // stop timer
           LPC_GPIO2->FIOCLR = TEST_1;          
           count += LPC_TIM0->TC;
           LPC_GPIOINT->IO0IntClr |= STOP_PULSE;               // clear stop pulse (1<<25)
           while((LPC_GPIOINT->IO0IntStatR & START_PULSE)==0); // check start pulse (1 << 24)
           LPC_TIM0->TCR = 0x2;        // reset timer
           LPC_GPIOINT->IO0IntClr |= START_PULSE;              // clear start pulse (1<<24)
           if(loop_count++ >= 10000) {
               loop_count = 0;
                led1 = 0;
                led2 = 0;
                led3 = 0;
                led4 = 0;
               
                if(count<150000)
                    led1 = 1;
                else if(count<200000)
                    led2 = 1;
                else if(count<250000)
                    led3 = 1;
                else
                    led4 = 1;
                count = 0;
           }
    }
}

23 Mar 2010

Hi John,

Thanks for your reply.

I am just curious about your project: How do you fire the laser? What type of laser diode that you use? More importantly, how do you capture the return signal?  I will be interested to know.

A few years ago, I built a 3D imaging system with 20 cameras and a laser line generator. Sure the technology is changed now and would be delighted to learn the new possibilities.

Thanks again,

Victor

24 Mar 2010

The laser is a 1mw red (630 nm?) laser pulsed by a fast discrete circuit.

The detector is a small PIN diode (to reduce capacitance) feeding a fast amplifier chain and a comparator.

John.