Need Faster Interrupt Handling!! >>>

Status
Not open for further replies.
I'd really rather not get into building a flip-flop array to handle this externally - trying to keep the component count at a minimum. An external logic circuit to handle this can be incredibly fast and would fit the bill but,... I suspect that with the right tweaking, the T3.5 can pull this off. Hoping to hear back from Frank this weekend to see if he has some tricks up his sleeve.

I did an initial design of the circuit board for this tonight while sitting on my hands. This thing is really small: 3.175"X1.725"
boardlatout01.jpg
 
Did you pick the T_3.5 for 5V compatibility or cost? The T_3.6 would have a better chance with faster F_BUS and F_CPU options - even then indeed it will take well executed tricks. Are the group of pins to start the read/write on the same port so a single read/edit/write can set them all?
 
Did you pick the T_3.5 for 5V compatibility or cost? The T_3.6 would have a better chance with faster F_BUS and F_CPU options - even then indeed it will take well executed tricks. Are the group of pins to start the read/write on the same port so a single read/edit/write can set them all?

Yes, the 5v compatibility was the deciding factor. There's a ton of lines here and using level shifters just would have made for a nighmare in designing a board.

Not sure I completely understand what you are asking about the pins. There is one single pin from the T3.5 that connects to all of the analog switches to control who sees the NVRAM.

When I want to read or write, I set all the data lines, address lines, OE and CE low, and WE high for a read, WE low for a write. Then it is just toggling the analog switches (pin3, SWITCH) for a moment to let the NVRAM do it's thing. I moved all the pins around to free up PORTC for the interrupt but toasted the rig literally setting it up to test it.
 
Here's how to get the fastest interrupt response by directly configuring the port register. I took the code from msg #3, removed all the unused stuff, then substituted these lines for the slow attachInterrupt(). I also added an analogWrite() on pin 2, for a test signal to cause the interrupt to happen.

Code:
void setup() {
  pinMode(29, OUTPUT);
  pinMode(30, INPUT);

  attachInterruptVector(IRQ_PORTB, &pulse); // directly attach function, all Port B pins
  CORE_PIN30_CONFIG |= PORT_PCR_IRQC(9); // 9=Rising Edge
  NVIC_SET_PRIORITY(IRQ_PORTB, 0);

  analogWrite(2, 128); // connect pin 2 to pin 30 for testing
}

FASTRUN
void pulse() {
  digitalWriteFast(29, HIGH);
  CORE_PIN30_CONFIG |= PORT_PCR_ISF; // clear interrupt status
  digitalWriteFast(29, LOW);
}

void loop() {
}

Here's the hardware on my desk, running this code on a Teensy 3.5.

DSC_0277_web.jpg

As you can see in this photo, I used a clip lead to connect the PWM on pin 2 to the interrupt input on pin 30.

Now for the bad news. Teensy 3.5 running at 120 MHz probably isn't fast enough to meet your needs. At least not using interrupts. Here's what I see on the scope.

file.png

This still image probably needs a little explanation. A video probably would be better, but you're going to have to use your imagination to visualize the pulse jumping round. I tried to capture it as best as possible using the scope's variable persistence setting.

The important point is the delay between the rising edge and the pulse varies. It's *usually* just a little over 200 ns (1 division on this horizontal scale), but it sometimes is as much as ~350 ns.

This sort of variability is very hard to see with a logic analyzer. You'd need to perform dozens, maybe hundreds of trials and somehow composite them. Of course, with good oscilloscope the screen shows every run as the PWM exercises the code hundreds of times per second.... so we see a bright blue waveform where the pulse is most of the time, and faint blue shadows that appear to bounce around for the unusual cases where bus latency of some other effect caused the interrupt to have more latency.

Unfortunately, there is quite a bit of variability in the latency (and a *lot* more without the NVIC priority setting). I'm afraid the worst case is quite far beyond the 220 ns you wanted. :(
 
Crazy as this may sound, polling might be an option. But it comes with huge caveats. You can't do anything else while waiting for the pulse. You also need to have interrupts disabled if you want consistently low latency. These place pretty severe limits on your program, pretty much nothing else can be done.

But if you work with that, here's the sort of latency polling can achieve (on the same 200 ns/div scale as the waveforms in msg #29)

file.png

Here's the code I ran for this test.

Code:
  pinMode(29, OUTPUT);
  pinMode(30, INPUT);
  analogWrite(2, 128); // connect pin 2 to pin 30 for testing
  noInterrupts(); // no USB :-(
}

void loop() {
  while (1) {
    if (digitalReadFast(30) == HIGH) {
      digitalWriteFast(29, HIGH);
      delayMicroseconds(1);
      digitalWriteFast(29, LOW);
      while (digitalReadFast(30) == HIGH) {
        // wait for pin 30 low
      }
    }
  }
}

Here's 1 last scope screenshot, where I've zoomed in the horizontal scale and placed the X-axis cursors on the pin 30 rising edge and the worst-case pin 29 rising edge. Looks like ~131 ns is possible, but only with this tight-loop polling and no other code in the mix.

file.png

All these tests were on Teensy 3.5 with the default 120 MHz clock.
 
Hi Paul!!

You know, I've been hoping that you would chime in on this! :) I've seen your name come up at least 100 times in all of my searches over the past few weeks regarding these Teensy devices! :)

My *longest* latency I can work with is 275ns. The shortest duration that the 6303 doesn't access the EPROM is 335ns. So, this ~130ns or even 250ns would still be workable.

My only question to you is, can the interrupt as you have shown it configured, be turned on and off from within the program and only setup for this quick response when needed? If so, then we have a winner. If at the time a read or write request is made, if this fast interrupt sequence can be initiated solely for throwing the analog switches for ~45ns and then back again, and then the fast interrupt be turned off so the T3.5 can resume running the "regular code" stuff, this will work.

Please tell me that I can switch the T3.5 in and out of this fast interrupt state. I don't need it to do anything else while it is waiting for the CE line to go high. Once it goes high, throw the analog switches for 45ns and then go back to "normal mode"...
 
@AshP … Post #30 is non-interrupt solution using a dedicated polling loop. The Teensy would be Polling ( sitting in the tight loop ) with all interrupts off waiting for the pin to change, or it could be doing other stuff until it stopped to do that polling loop.
 
You can disable the pin's interrupt by writing to CORE_PIN30_CONFIG. Or you can disable all interrupts with noInterrupts(), as I showed in the code on msg #30. The NVIC also has a way to mask each interrupt. Use NVIC_ENABLE_IRQ(IRQ_PORTB) and NVIC_DISABLE_IRQ(IRQ_PORTB).
 
Well, this is VERY promising! I just set this up myself and overclocked it has only a 90ns latency! Time to play more with the code! :)

Thank you!!

90ns.png
 
Status
Not open for further replies.
Back
Top