How to clear an external interrupt's status flag in Teensyduino for Teensy 3.2

Status
Not open for further replies.
Hi.

I'm trying to port some code I wrote for an Arduino Mega2560 (in the Arduino IDE) to a Teensy 3.2 (using Teensyduino) but I'm stuck on how to do the Teensy equivalent of this line that clears the external interrupt's status flag:

EIFR=bit(INTF5) // INTF5 is the bit in EIFR relating to interrupt 1 (on pin 3!) of the Arduino Mega2560

Given how fruitless my searches have been, I take it not many people clear this flag manually (or it's so obvious to everybody else how to do it that they haven't had to ask :)

I read in Nick Gammon's excellent article on interrupts (where I got that line of code from) that it should be done immediately prior to enabling the interrupt so that your ISR doesn't immediately fire after the interrupt is enabled due to a previously flagged interrupt instance (I periodically disable/re-enable the interrupt on the pin.) Then when trying to find out how to do it on the Teensy I came across Paul's article on interrupts (which seems to only relate to AVR Teensys?) which also refers to resetting the interrupt flag before setting the interrupt mask.

For completeness, these are all the lines of code that relate to managing the external interrupt that I'm porting from the Mega2560 to the Teensy 3.2:
EIFR=bit(INTF5);
attachInterrupt(1, ISR_Rx, FALLING);
detachInterrupt(1);

I believe the other two lines will change to the following (staying with pin 3):
attachInterrupt(3, ISR_Rx, FALLING);
detachInterrupt(3);

All help will be much appreciated. Thanks for your time.
 
Interrupts don't get queued while they are disabled. detachInterrupt accomplishes what you want.

Code:
auto& serial = Serial;

volatile uint32_t isr_counter = 0;
const uint8_t pin_nr = 3;

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

    pinMode(pin_nr, OUTPUT);

    attachInterrupt(pin_nr, pinIsr, FALLING);
    detachInterrupt(pin_nr);

    togglePin();
    delay(10);
    serial.printf("isr_counter before attachInterrupt: %i\n", isr_counter);
    attachInterrupt(pin_nr, pinIsr, FALLING);
    delay(10);
    serial.printf("isr_counter after attachInterrupt: %i\n", isr_counter);
    togglePin();
    delay(10);
    serial.printf("isr_counter after extra toggle: %i\n", isr_counter);
}

void togglePin() {
    digitalWriteFast(pin_nr, HIGH);
    delayMicroseconds(10);
    digitalWriteFast(pin_nr, LOW);
}

void pinIsr() {
    isr_counter++;
}

void loop() {}

Output:
isr_counter before attachInterrupt: 0
isr_counter after attachInterrupt: 0
isr_counter after extra toggle: 1


Teensy 3.x has IO port interrupts. There is a port ISR that dispatches to the individual pin functions and clears the pin interrupt flags (PORTx_ISFR). The Kinetis MCU manuals are here, if you want details:
https://www.pjrc.com/teensy/datasheets.html
 
Thanks for your reply, tni, but I believe that's not always going to be the case. I read in another thread between doughboy and Paul that the external interrupt status flag is cleared by "system" code before the "user" code is executed in the ISR. So, it is possible for the interrupt status flag to be reset and then before my ISR can issue the dettachinterrupt command the status flag is set again by another event that arrived really close behind the first one. All of which means that I can exit the ISR with the interrupt disabled but with the status flag set. This is a showstopper for me as I need all nodes on the bus to trigger on the first, and only the first, falling edge of a whole bunch of bits arriving at >= 1Mb/s (it synchronises the start of a period for all nodes on the bus).

I've tried to make sense of the material you pointed me to in those links - am I right in thinking that, for example, the interrupt status flag for interrupt 3 on pin 3 is in PORTA_ISFR and that it can be reset to zero by this command: PORTA_ISFR = CORE_PIN3_BITMASK; ?
 
I read in another thread between doughboy and Paul that the external interrupt status flag is cleared by "system" code before the "user" code is executed in the ISR. So, it is possible for the interrupt status flag to be reset and then before my ISR can issue the dettachinterrupt command the status flag is set again by another event that arrived really close behind the first one. All of which means that I can exit the ISR with the interrupt disabled but with the status flag set.
Correct.
I've tried to make sense of the material you pointed me to in those links - am I right in thinking that, for example, the interrupt status flag for interrupt 3 on pin 3 is in PORTA_ISFR and that it can be reset to zero by this command: PORTA_ISFR = CORE_PIN3_BITMASK; ?
Yes.
 
Great! Thanks very much for your help, tni.

For anyone else that stumbles upon this: for Teensy 3.2, the interrupt numbers for the interrupts on the digital pins correspond to their pin numbers (e.g. digital pin 3 has interrupt 3); the interrupt status flags for interrupts 3 and 4 are in PORTA_ISFR; 9, 10, 11, 12, 13, 15, 22 and 23 are in PORTC_ISFR; and 2, 5, 6, 7, 8, 14, 20 and 21 are in PORTD_ISFR; there is already a defined bitmask for each status flag (e.g. CORE_PIN3_BITMASK); to manually clear an interrupt status flag, clear the relevant bit in the relevant register (e.g. PORTA_ISFR = CORE_PIN3_BITMASK). attachInterrupt and detachInterrupt in teensyduino work just like they do in the arduino environment (e.g. attachInterrupt(3, my_ISR, FALLING) and detachInterrupt(3)).
 
For anyone else that stumbles upon this

I did, in fact, stumble across this thread while searching for the exact same function. By looking through pins_arduino.h and pins_teensy.c, I came up with this method:
Code:
const uint32_t pinISF = 1 << 24;
const uint8_t interruptPin = 3;

void setup() {
  volatile uint32_t *pinConfigRegPtr;
  uint32_t pinConfigRegValue;

  pinConfigRegPtr = portConfigRegister(interruptPin);
  pinConfigRegValue = *pinConfigRegPtr;
  pinConfigRegValue |= pinISF;
  *pinConfigRegPtr = pinConfigRegValue;
}

I like this because the pin number can actually be a run-time variable.
 
Great! Thanks very much for your help, tni.

For anyone else that stumbles upon this: for Teensy 3.2, the interrupt numbers for the interrupts on the digital pins correspond to their pin numbers (e.g. digital pin 3 has interrupt 3); the interrupt status flags for interrupts 3 and 4 are in PORTA_ISFR; 9, 10, 11, 12, 13, 15, 22 and 23 are in PORTC_ISFR; and 2, 5, 6, 7, 8, 14, 20 and 21 are in PORTD_ISFR; there is already a defined bitmask for each status flag (e.g. CORE_PIN3_BITMASK); to manually clear an interrupt status flag, clear the relevant bit in the relevant register (e.g. PORTA_ISFR = CORE_PIN3_BITMASK). attachInterrupt and detachInterrupt in teensyduino work just like they do in the arduino environment (e.g. attachInterrupt(3, my_ISR, FALLING) and detachInterrupt(3)).

How different would this be to do on the Teensy 4.1?

Im currently doing an application where I connect 8 sensors to the teensy and there is an ISR for each of them. However, the operator can choose which of the sensors are used or not used on a certain job. Im using a row of DIP switches on 8 inputs to attach/detach the ISRs for the respective sensors because I dont want any stray noise or so to falsely trigger the ISRs of the sensors that arent connected.
 
Status
Not open for further replies.
Back
Top