Jitter on Due interrupts

Hey,
This is a slight resurrection of an older topic (more than 2 years!)here.

Where essentially I am trying to set a pin high at a programmable time using an interrupt. A simple example of this is below, assuming you have physically connected pin 6 and 7.

const int strt = 7;
const int ind=9;
const int intrpin = 6; // pin to detect change in state

void InterIn()
{
  digitalWriteDirect(ind,1);
  digitalWriteDirect(ind,0);
}

void setup() {
Serial.begin(115200);

pinMode(strt ,OUTPUT);
digitalWrite(strt ,0);
pinMode(ind,OUTPUT);
digitalWrite(ind);
pinMode(intrpin,INPUT);

attachInterrupt(intrpin,InterIn,RISING);

}

void loop() {
    char c = '#';
  //read serial byte if one is available
  if (Serial.available() > 0)
  {
   // delay(1);
    c = Serial.read();  
  digitalWriteDirect(strt,1);
  digitalWriteDirect(strt,0);
      
  }

}

Previously there was a fixed delay based on the time taken for the PIOA_HANDLER in WInterrupts.c to run through all 32 pins. This delay was ok for my application as it was fixed, but my memories are a little hazy! I am looking at it again today, and I think the behaviour is different as of this change here. This does seem to have improved the delay - its now less than 2us compared to 4us! But I am seeing a jitter of around 1us,
shown in the time from the blue trace going low, to the pink trace going high.
This is the 2nd measurement on the table in the image. Imgur: The magic of the Internet

I think for my application the most important thing is that this delay is the same each time. Is it possible to do this? The ideal solution would be for something within my own sketch, so that I didnt have to distribute my own modified version of the arduino core along with my code.

Thanks for any help you can offer!

Cheers
Jimbles

Assuming intrpin = 9 (PC21), and you want a constant time to trigger an interrupt, I guess you will have tp override PIOC_Handler, provided you won't need to trigger any other interrupt via a PCx pin.

Or modify Winterrupts.h

Hey, yeah I thought that might be the case! Im guess there is more to it that just defining PIOC_Handler in my own sketch? Do you know of a good guide on how to do this? Thanks very much

Prior to override PIOC_Handler (if winterrupts.h doesn't mess with that, don't know, you will have to check…), you need to specify these registers:
PIO_PER
PIO_ODR
PIO_PUER
PIO_IFER
PIO_IER
then NVIC_EnableIRQ(PIOC_IRQn);

That's a lot of datasheet to read (Sam3x datasheet section 31) alas! :slight_smile:

Could you be receiving spurious interrupts for pins that are configured as inputs but are floating? (I don't
1us of jitter sounds like a lot for an 84MHz cpu...
You could try setting all your unused pins for INPUT_PULLUP or something, or start instrumenting the interrupt code to see what's happening.

Oh god 1495 pages of datasheet...

I was thinking I could change just one of the PIOX_Handlers from this:

void PIOC_Handler(void) {
  uint32_t isr = PIOC->PIO_ISR;
  uint8_t leading_zeros;
  while((leading_zeros=__CLZ(isr))<32)
  {
    uint8_t pin=32-leading_zeros-1;
    if(callbacksPioC[pin]) callbacksPioC[pin]();
    isr=isr&(~(1<<pin));
  }
}

which loops through the array to find which callback pin to use, to something like this

void PIOC_Handler(void) {
callbacksPioC[targetpin]();

}

which does nothing but do the callback on the pin I want - assuming I figure out what the value for targetpin should actually be, which I guess comes from g_APinDescription[pin].ulPin;

Maybe I should just edit the core to see if this works first, before worrying about overriding it. A cursory google says that the overriding is hard!

Section 31 represents 51 pages "only".

Note that before overrinding PIOC_Handler, you will need to declare the prototype as a WEAK function.

westfw:
Could you be receiving spurious interrupts for pins that are configured as inputs but are floating? (I don't
1us of jitter sounds like a lot for an 84MHz cpu...
You could try setting all your unused pins for INPUT_PULLUP or something, or start instrumenting the interrupt code to see what's happening.

Hey! That sounds like a good idea, currently the unused pins are floating and there is no mention of them in the sketch, so Im not sure what the default behaviour is on the due for unused pins.

Apologies, but im not sure what you mean by "instrumenting" the interrupt code?

Apologies, but im not sure what you mean by "instrumenting" the interrupt code?

Add some code to keep track of which interrupts have actually occurred, say by putting in:

  uint32_t isr = PIOC->PIO_ISR;
PORTC_INTERRUPTS |= isr;  // keep track of all the PORTC interrupts that have ever happened

And then some other code to LOOK at the PORTC_INTERRUPTS globals.
The clz-based code really shouldn't be any more jittery than the old code, especially if only one pin is interrupting.
(and I've now looked at the code - it LOOKS like it only enables interrupts on pins that you've actually called attachInterrupt() for.)

Oh right, I see what you mean. That makes sense. I was thinking I could also attach some interrupts to the floating pins and see if the ISR gets triggered.

westfw:
(and I've now looked at the code - it LOOKS like it only enables interrupts on pins that you've actually called attachInterrupt() for.)

If this is the case then im wondering if it would be possible to speed the process up by looping through all pins? Although this would make a difference for interrupts on pins above the 0 position.

I agree with you in that looking at the code, cant quite see why the current version and the version from 2015 would be any different in terms of jitter - I might be remembering incorrectly that it was fixed.

I AM STUPID

I went back and tested my simple working example:

const int strt = 7;
const int ind = 24;
const int intrpin = 25; // pin to detect change in state

void InterIn()
{
 digitalWriteDirect(ind, 1);
 digitalWriteDirect(ind, 0);
}

void setup() {
 Serial.begin(115200);

 pinMode(strt, OUTPUT);
 digitalWrite(strt, 0);
 pinMode(ind, OUTPUT);
 digitalWrite(ind,0);
 pinMode(intrpin, INPUT);

 attachInterrupt(intrpin, InterIn, RISING);

}

void loop() {

 digitalWriteDirect(strt, 1);
 delay(1);
 digitalWriteDirect(strt, 0);
 delay(1);
}

//taken from http://forum.arduino.cc/index.php?topic=129868.15
inline void digitalWriteDirect(int pin, int val) {
 if (val) g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
}

And I get no jitter! So it must be something inside by larger more complicated code which is the source of the jitter. I hadnt realised that things could be slowing the speed of these PIOX_Handler routines.

Do you guys know which things could be slowing this down? I have some calls to micros() and Serial.Available() and things like that which I guess could be a good bet.

Thanks and sorry for my stupidity!