espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.75k stars 7.44k forks source link

Interrupt functions cause a double Arduino pin -> GPIO pin number conversion #10367

Closed per1234 closed 2 months ago

per1234 commented 2 months ago

Board

Arduino Nano ESP32

Device Description

N/A

Hardware Configuration

N/A

Version

IDE Name

Arduino IDE, Arduino CLI

Operating System

N/A

Flash frequency

N/A

PSRAM enabled

yes

Upload speed

N/A

Description

The first parameter of the attachInterrupt function is an interrupt number. The digitalPinToInterrupt function can be used to derive the interrupt number from the Arduino pin number. So it is common to use the two functions together. For example:

attachInterrupt(digitalPinToInterrupt(interruptPin), interruptISR, CHANGE);

Arduino pin numbers are arbitrary integers used to reference an I/O pin in Arduino code. The Arduino pin number has traditionally been mapped to the low level pin identifiers (which won't necessarily have any direct correlation to the pin number) by the core variant. When this platform was created, that standard approach was abandoned and the low level GPIO numbers were used as Arduino pin numbers, forcing any mapping to be done via macros (e.g., D2). When support for the Nano ESP32 board was added to the platform, it was necessary to implement support for true Arduino pin numbers, while also retaining the GPIO system. This was done in some cases by passing the pin number argument of functions through a digitalPinToGPIONumber conversion function.

The digitalPinToInterrupt function passes the pin number argument to digitalPinToGPIONumber, which is appropriate:

https://github.com/espressif/arduino-esp32/blob/7018cd114d00249674567846c9d67fbb3a1240a3/cores/esp32/Arduino.h#L145

The attachInterrupt function passes the interrupt number argument to digitalPinToGPIONumber:

https://github.com/espressif/arduino-esp32/blob/7018cd114d00249674567846c9d67fbb3a1240a3/cores/esp32/io_pin_remap.h#L44

πŸ› This causes the interrupt number to be treated as an Arduino pin number, and that pin number converted to a GPIO number. In the case where the Arduino pin number is different from the GPIO number, this causes the interrupt to be attached to a different pin than the one the user intended.

Sketch

  1. Select the Nano ESP32 board from Arduino IDE's Tools > Board menu.
  2. Select Tools > Pin Numbering > By Arduino pin (default) from the Arduino IDE menus.
  3. Upload the following sketch to a Nano ESP32 board:

    const int interruptPin = D2;
    volatile bool interruptFlag = false;
    
    void setup() {
     Serial.begin(9600);
     pinMode(interruptPin, INPUT_PULLUP);
     // Also set the pull-up on the pin that is incorrectly attached due to the bug.
     pinMode(digitalPinToGPIONumber(interruptPin), INPUT_PULLUP);
     attachInterrupt(digitalPinToInterrupt(interruptPin), interruptISR, CHANGE);
    }
    
    void loop() {
     if (interruptFlag) {
       interruptFlag = false;
       Serial.println("interrupt triggered");
     }
    }
    
    void interruptISR() {
     interruptFlag = true;
    }
  4. Open Serial Monitor.
  5. Connect the pin labeled "D2" on the Nano ESP32 silkscreen to ground. πŸ› Nothing is printed in Serial Monitor, indicating that the interrupt was not triggered even though the sketch code should have attached it to Arduino pin 2.
  6. Connect the pin labeled "D5" on the Nano ESP32 silkscreen to ground. πŸ› "interrupt triggered" is printed in Serial Monitor, even though the sketch code should not have attached the interrupt to Arduino pin 5.

Debug Message

N/A

Other Steps to Reproduce

I provided instructions for reproducing the fault in the "Sketch" section above.

Additional context

This was previously reported at https://github.com/espressif/arduino-esp32/issues/10209, but the reporter closed that issue after they found a workaround, even though the bug was not fixed.


CC: @pillo79

Additional reports

I have checked existing issues, online documentation and the Troubleshooting Guide