mirror of
				https://github.com/0xFEEDC0DE64/arduino-esp32.git
				synced 2025-11-04 08:01:38 +01:00 
			
		
		
		
	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
		
			
				
	
	
		
			83 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 Repeat timer example
 | 
						|
 | 
						|
 This example shows how to use hardware timer in ESP32. The timer calls onTimer
 | 
						|
 function every second. The timer can be stopped with button attached to PIN 0
 | 
						|
 (IO0).
 | 
						|
 | 
						|
 This example code is in the public domain.
 | 
						|
 */
 | 
						|
 | 
						|
// Stop button is attached to PIN 0 (IO0)
 | 
						|
#define BTN_STOP_ALARM    0
 | 
						|
 | 
						|
hw_timer_t * timer = NULL;
 | 
						|
volatile SemaphoreHandle_t timerSemaphore;
 | 
						|
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 | 
						|
 | 
						|
volatile uint32_t isrCounter = 0;
 | 
						|
volatile uint32_t lastIsrAt = 0;
 | 
						|
 | 
						|
void IRAM_ATTR onTimer(){
 | 
						|
  // Increment the counter and set the time of ISR
 | 
						|
  portENTER_CRITICAL_ISR(&timerMux);
 | 
						|
  isrCounter++;
 | 
						|
  lastIsrAt = millis();
 | 
						|
  portEXIT_CRITICAL_ISR(&timerMux);
 | 
						|
  // Give a semaphore that we can check in the loop
 | 
						|
  xSemaphoreGiveFromISR(timerSemaphore, NULL);
 | 
						|
  // It is safe to use digitalRead/Write here if you want to toggle an output
 | 
						|
}
 | 
						|
 | 
						|
void setup() {
 | 
						|
  Serial.begin(115200);
 | 
						|
 | 
						|
  // Set BTN_STOP_ALARM to input mode
 | 
						|
  pinMode(BTN_STOP_ALARM, INPUT);
 | 
						|
 | 
						|
  // Create semaphore to inform us when the timer has fired
 | 
						|
  timerSemaphore = xSemaphoreCreateBinary();
 | 
						|
 | 
						|
  // Use 1st timer of 4 (counted from zero).
 | 
						|
  // Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more
 | 
						|
  // info).
 | 
						|
  timer = timerBegin(0, 80, true);
 | 
						|
 | 
						|
  // Attach onTimer function to our timer.
 | 
						|
  timerAttachInterrupt(timer, &onTimer, true);
 | 
						|
 | 
						|
  // Set alarm to call onTimer function every second (value in microseconds).
 | 
						|
  // Repeat the alarm (third parameter)
 | 
						|
  timerAlarmWrite(timer, 1000000, true);
 | 
						|
 | 
						|
  // Start an alarm
 | 
						|
  timerAlarmEnable(timer);
 | 
						|
}
 | 
						|
 | 
						|
void loop() {
 | 
						|
  // If Timer has fired
 | 
						|
  if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
 | 
						|
    uint32_t isrCount = 0, isrTime = 0;
 | 
						|
    // Read the interrupt count and time
 | 
						|
    portENTER_CRITICAL(&timerMux);
 | 
						|
    isrCount = isrCounter;
 | 
						|
    isrTime = lastIsrAt;
 | 
						|
    portEXIT_CRITICAL(&timerMux);
 | 
						|
    // Print it
 | 
						|
    Serial.print("onTimer no. ");
 | 
						|
    Serial.print(isrCount);
 | 
						|
    Serial.print(" at ");
 | 
						|
    Serial.print(isrTime);
 | 
						|
    Serial.println(" ms");
 | 
						|
  }
 | 
						|
  // If button is pressed
 | 
						|
  if (digitalRead(BTN_STOP_ALARM) == LOW) {
 | 
						|
    // If timer is still running
 | 
						|
    if (timer) {
 | 
						|
      // Stop and free timer
 | 
						|
      timerEnd(timer);
 | 
						|
      timer = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |