Skip to content

Commit 2e50aa5

Browse files
committed
feat(gpio): uses IRAM lambda and fixes volatile operation
1 parent 36522c1 commit 2e50aa5

File tree

2 files changed

+41
-34
lines changed

2 files changed

+41
-34
lines changed

libraries/ESP32/examples/GPIO/FunctionalInterruptLambda/FunctionalInterruptLambda.ino

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,42 @@ const unsigned long DEBOUNCE_DELAY_MS = 50; // 50ms debounce delay
6767
// State-based debouncing to prevent hysteresis issues
6868
volatile bool lastButtonState = HIGH; // Track last stable state (HIGH = released)
6969

70+
// Global lambda function (declared at file scope) - ISR in IRAM
71+
IRAM_ATTR std::function<void()> changeModeLambda = []() {
72+
// Simple debouncing: check if enough time has passed since last interrupt
73+
unsigned long currentTime = millis();
74+
if (currentTime - lastButtonInterruptTime < DEBOUNCE_DELAY_MS) {
75+
return; // Ignore this interrupt due to bouncing
76+
}
77+
78+
// Read current pin state to determine edge type
79+
bool currentState = digitalRead(BUTTON_PIN);
80+
81+
// State-based debouncing: only process if state actually changed
82+
if (currentState == lastButtonState) {
83+
return; // No real state change, ignore (hysteresis/noise)
84+
}
85+
86+
// Update timing and state
87+
lastButtonInterruptTime = currentTime;
88+
lastButtonState = currentState;
89+
90+
if (currentState == LOW) {
91+
// FALLING edge detected (button pressed) - set flag for main loop
92+
// volatile variables require use of temporary value transfer
93+
uint32_t temp = buttonPressCount + 1;
94+
buttonPressCount = temp;
95+
buttonPressed = true;
96+
ledStateChanged = true; // Signal main loop to toggle LED
97+
} else {
98+
// RISING edge detected (button released) - set flag for main loop
99+
// volatile variables require use of temporary value transfer
100+
uint32_t temp = buttonReleaseCount + 1;
101+
buttonReleaseCount = temp;
102+
buttonReleased = true;
103+
}
104+
};
105+
70106
void setup() {
71107
Serial.begin(115200);
72108
delay(1000); // Allow serial monitor to connect
@@ -83,38 +119,7 @@ void setup() {
83119
// This toggles the LED on button press (FALLING edge)
84120
Serial.println("Setting up CHANGE mode lambda for LED toggle");
85121

86-
// Simplified lambda with minimal captures
87-
std::function<void()> changeModeLambda = []() {
88-
// Simple debouncing: check if enough time has passed since last interrupt
89-
unsigned long currentTime = millis();
90-
if (currentTime - lastButtonInterruptTime < DEBOUNCE_DELAY_MS) {
91-
return; // Ignore this interrupt due to bouncing
92-
}
93-
94-
// Read current pin state to determine edge type
95-
bool currentState = digitalRead(BUTTON_PIN);
96-
97-
// State-based debouncing: only process if state actually changed
98-
if (currentState == lastButtonState) {
99-
return; // No real state change, ignore (hysteresis/noise)
100-
}
101-
102-
// Update timing and state
103-
lastButtonInterruptTime = currentTime;
104-
lastButtonState = currentState;
105-
106-
if (currentState == LOW) {
107-
// FALLING edge detected (button pressed) - set flag for main loop
108-
buttonPressCount++;
109-
buttonPressed = true;
110-
ledStateChanged = true; // Signal main loop to toggle LED
111-
} else {
112-
// RISING edge detected (button released) - set flag for main loop
113-
buttonReleaseCount++;
114-
buttonReleased = true;
115-
}
116-
};
117-
122+
// Use the global lambda function
118123
attachInterrupt(BUTTON_PIN, changeModeLambda, CHANGE);
119124

120125
Serial.println();

libraries/ESP32/examples/GPIO/FunctionalInterruptLambda/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This example demonstrates how to use lambda functions with FunctionalInterrupt f
88
2. **LED toggle on button press** (FALLING edge)
99
3. **Edge type detection** using digitalRead() within ISR
1010
4. **Hardware debouncing** with configurable timeout
11+
5. **IRAM_ATTR lambda declaration** for optimal ISR performance in RAM
1112

1213
## Hardware Setup
1314

@@ -46,9 +47,10 @@ This example demonstrates a simple CHANGE mode lambda interrupt that:
4647

4748
## Lambda Function Pattern
4849

49-
### CHANGE Mode Lambda (No Captures)
50+
### CHANGE Mode Lambda with IRAM Declaration
5051
```cpp
51-
std::function<void()> changeModeLambda = []() {
52+
// Global lambda declared with IRAM_ATTR for optimal ISR performance
53+
IRAM_ATTR std::function<void()> changeModeLambda = []() {
5254
// Debouncing check
5355
unsigned long currentTime = millis();
5456
if (currentTime - lastButtonInterruptTime < DEBOUNCE_DELAY_MS) {

0 commit comments

Comments
 (0)