Skip to content

Commit b5ac95b

Browse files
committed
Update RepeatTimer example
Implement semaphore and mutex to safeguard the ISR. This is the proper way to handle hardware Interrupts with FreeRTOS. The more regular approach may/will lead to exceptions
1 parent e873d57 commit b5ac95b

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

libraries/ESP32/examples/Timer/RepeatTimer/RepeatTimer.ino

+31-9
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@
1212
#define BTN_STOP_ALARM 0
1313

1414
hw_timer_t * timer = NULL;
15+
volatile SemaphoreHandle_t timerSemaphore;
16+
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
1517

16-
void onTimer(){
17-
static unsigned int counter = 1;
18+
volatile uint32_t isrCounter = 0;
19+
volatile uint32_t lastIsrAt = 0;
1820

19-
Serial.print("onTimer no. ");
20-
Serial.print(counter);
21-
Serial.print(" at ");
22-
Serial.print(millis());
23-
Serial.println(" ms");
24-
25-
counter++;
21+
void IRAM_ATTR onTimer(){
22+
// Increment the counter and set the time of ISR
23+
portENTER_CRITICAL_ISR(&timerMux);
24+
isrCounter++;
25+
lastIsrAt = millis();
26+
portEXIT_CRITICAL_ISR(&timerMux);
27+
// Give a semaphore that we can check in the loop
28+
xSemaphoreGiveFromISR(timerSemaphore, NULL);
29+
// It is safe to use digitalRead/Write here if you want to toggle an output
2630
}
2731

2832
void setup() {
@@ -31,6 +35,9 @@ void setup() {
3135
// Set BTN_STOP_ALARM to input mode
3236
pinMode(BTN_STOP_ALARM, INPUT);
3337

38+
// Create semaphore to inform us when the timer has fired
39+
timerSemaphore = xSemaphoreCreateBinary();
40+
3441
// Use 1st timer of 4 (counted from zero).
3542
// Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more
3643
// info).
@@ -48,6 +55,21 @@ void setup() {
4855
}
4956

5057
void loop() {
58+
// If Timer has fired
59+
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
60+
uint32_t isrCount = 0, isrTime = 0;
61+
// Read the interrupt count and time
62+
portENTER_CRITICAL(&timerMux);
63+
isrCount = isrCounter;
64+
isrTime = lastIsrAt;
65+
portEXIT_CRITICAL(&timerMux);
66+
// Print it
67+
Serial.print("onTimer no. ");
68+
Serial.print(isrCount);
69+
Serial.print(" at ");
70+
Serial.print(isrTime);
71+
Serial.println(" ms");
72+
}
5173
// If button is pressed
5274
if (digitalRead(BTN_STOP_ALARM) == LOW) {
5375
// If timer is still running

0 commit comments

Comments
 (0)