ISR on rising edge

Hello,

i have a square wave signal variing from 1-2 MHz and was wondering if i can detect every rising edge of the signal with the buit-in command attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)?
In other words how fast is this command?

Thanks!

No, you can not field interrupts at a 1-2MHz rate. That is WAY too fast.

I'm using the arduino due by the way. Do you know how fast this command is at max. ? I can't find anything related in the datasheet

jannik_b:
I'm using the arduino due by the way. Do you know how fast this command is at max. ? I can't find anything related in the datasheet

I have not looked at a data sheet for your particular processor, but I suspect there is narrative describing the steps the processor takes to process an interrupt and the return from the interrupt. From that you can determine the exect number of processor steps taken and that will allow you to add up the times and that will tell you the minimum time for an interrupt.
Then add the times for the instructions in your interrupt code to the processor interrupt time. The sum is exactly how long each interrupt will take.
Paul

jannik_b:
Hello,

i have a square wave signal variing from 1-2 MHz and was wondering if i can detect every rising edge of the signal with the buit-in command attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)?
In other words how fast is this command?

The speed of the attachInterrupt() "command" is irrelevant. What you care about is the speed of servicing the interrupt (as @Paul_KD7HB described).

In fact, for fastest servicing you would not use attachInterrupt() at all. Rather service the raw interrupt vector yourself.

Your Google search term is "Arduino due interrupt latency"

One discussion is here

attachInterrupt() is handy but a bit slow.

A 1 to 2 MHz pulse (even 2.5 MHz) can be easily detected either with a blocking code without interruptions, e.g. in the sketch below:

/*******************************************************************/
/*                       Test PIO Reading                          */
/*    Hook a jumper between pin 2 (PB25) and pin 24 (PA15)         */
/*******************************************************************/

#define INT_MASK   (PIO_PA15)

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pio_setup();
  tc_setup();
}
void loop() {
  static uint32_t Count;
  while (true)
  {
    while (!(PIOA->PIO_ISR & INT_MASK));  // Do nothing until PA15 falls down
    // Do something .....
    if (Count++ == 2000000)
    {
      Count = 0;
      PIOB->PIO_ODSR ^= PIO_ODSR_P27;  // 1 Hz LED blinking
    }
  }
}
/*****************************************************************/
void tc_setup() {

  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                      // TC0 power ON : Timer Counter 0 channel 0 IS TC0

  PIOB->PIO_PDR = PIO_PDR_P25;                            // Set the GPIO to the peripheral
  PIOB->PIO_ABSR |= PIO_PB25B_TIOA0;

  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC       // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR         // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;          // Set TIOA0 on RC compare match

  TC0->TC_CHANNEL[0].TC_RC = 21;  //<*********************  Frequency = (Mck/2)/TC_RC 
  TC0->TC_CHANNEL[0].TC_RA = 10;  //<********************   Any Duty cycle in between 1 and TC_RC

  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable

}

/*******************************************************************/
void pio_setup(void)
{
  PMC->PMC_PCER0 = PMC_PCER0_PID11;   // PIOA power ON

  PIOA->PIO_PER = INT_MASK;         // enable paralel input - output
  PIOA->PIO_PUER = INT_MASK;        // enable light pull up
  PIOA->PIO_IFER = INT_MASK;        // enable glitch filter (1/2 clock cycle glitches discared)
  PIOA->PIO_AIMER = INT_MASK;       // The interrupt source is described in PIO_ELSR
  PIOA->PIO_ELSR = INT_MASK;        // enable low level detection
}

… Or with interruptions for 1-2 MHz pulse, after altering winterrupts.c as indicated in the skecth below:

/*******************************************************************/
/*                       Test PIO Interrupts                       */
/*    Hook a jumper between pin 2 (PB25) and pin 24 (PA15)         */
/*    Do the below modifications in winterrupts.c                  */
/*******************************************************************/

// Winterrupts.c has to be modified since attachinterrupts is too slow
// ...package/arduino/hardware/sam/1.6.x/cores/arduino/Winterrupts
/*
  void PIOA_Handler(void) __attribute((weak));  // <***** Add this attribute before each PIO Handler
  void PIOA_Handler(void) {
  uint32_t isr = PIOA->PIO_ISR;
  uint32_t i;
  for (i=0; i<32; i++, isr>>=1) {
    if ((isr & 0x1) == 0)
      continue;
    if (callbacksPioA[i])
      callbacksPioA[i]();
  }
  }

*/
#define INT_MASK  (PIO_PA15)

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(7, OUTPUT);

  pio_setup();
  tc_setup();
}
void loop() {
}
/*****************************************************************/
void tc_setup() {

  PMC->PMC_PCER0 |= PMC_PCER0_PID27;                      // TC0 power ON : Timer Counter 0 channel 0 IS TC0

  PIOB->PIO_PDR = PIO_PDR_P25;                            // Set the GPIO to the peripheral
  PIOB->PIO_ABSR |= PIO_PB25B_TIOA0;

  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC       // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR         // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;          // Set TIOA0 on RC compare match

  TC0->TC_CHANNEL[0].TC_RC = 21;  //<*********************  Frequency = (Mck/2)/TC_RC 
  TC0->TC_CHANNEL[0].TC_RA = 10;  //<********************   Any Duty cycle in between 1 and TC_RC

  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable

}

/*******************************************************************/
void pio_setup(void)
{
  PMC->PMC_PCER0 = PMC_PCER0_PID11;   // PIOA power ON

  PIOA->PIO_PER = INT_MASK;         // enable parallel input - output
  PIOA->PIO_PUER = INT_MASK;        // enable light pull up
  PIOA->PIO_IFER = INT_MASK;        // enable glitch filter (1/2 clock cycle glitches discarted)
  PIOA->PIO_AIMER = INT_MASK;       // The interrupt source is described in PIO_ELSR
  PIOA->PIO_ELSR = INT_MASK;        // enable low level detection

  PIOA->PIO_IER = INT_MASK;         // enable interrupt
  NVIC_EnableIRQ(PIOA_IRQn);
}

void PIOA_Handler(void)
{
  static uint32_t Count;
  // uint32_t status = PIOA->PIO_ISR;
  PIOA->PIO_ISR;

  //DO something ...
  // if (status & INT_MASK)
  // {
  // 1 Hz LED blinking
  if (Count++ == 2000000)
  {
    Count = 0;
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;
    // do something...
  }
  //}
}

jannik_b:
i have a square wave signal variing from 1-2 MHz and was wondering if i can detect every rising edge of the signal with the buit-in command attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)?
In other words how fast is this command?

What processing do you need on every rising edge? Are you just counting them? If so, external hardware counters might be the answer.

Looking for something like this?