Skip to content

Instantly share code, notes, and snippets.

@egeltje
Created December 24, 2018 10:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egeltje/db23f8c7b22002a30c68dad9b55c0f4d to your computer and use it in GitHub Desktop.
Save egeltje/db23f8c7b22002a30c68dad9b55c0f4d to your computer and use it in GitHub Desktop.
handling M5stack button interrupts in FreeRTOS
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include <M5Stack.h>
#include <esp_log.h>
//#include <Arduino.h>
#include "sdkconfig.h"
#define ESP_INTR_FLAG_DEFAULT 0
#define CONFIG_LOG_DEFAULT_LEVEL 5 // set to debug, check with serial monitor
static const char* TAG = "gpio_button"; // tag for logging
static TaskHandle_t xButtonHandle = NULL; // task handle for interrupt callback
static void IRAM_ATTR vfnButtonISR(void* vpArg) {
/***
Interrupt routine for handling GPIO interrupts.
vpArg is a pointer to the GPIO number.
***/
uint32_t ulGPIONumber = (uint32_t) vpArg; // get the triggering GPIO
if (gpio_get_level( (gpio_num_t) ulGPIONumber) == 0) { // only when pressed
xTaskNotifyFromISR(xButtonHandle, // task to notify
ulGPIONumber - 37, // 32 bit integer for passing a value
eSetBits, // notify action (pass value in this case)
NULL); // wake a higher prio task (default behavior)
}
portYIELD_FROM_ISR(); // if notified task has higher prio then current interrupted task, set it to the head of the task queue
}
static void vfnButtonTask(void* vpArg) {
/***
Task for handling interrupts generated by button presses on the M5Stack
vpArg is a pointer to the passed arguments. Not used in this task.
***/
uint32_t ulNotifiedValue = 0;
BaseType_t xResult;
while (1) {
m5.Lcd.setCursor(0, 0);
m5.Lcd.printf("running on core %d", xPortGetCoreID());
m5.Lcd.setCursor(0, 40);
xResult = xTaskNotifyWait(pdFALSE, // don't clear bits on entry
0xFFFFFFFF, // clear all bits on exit
&ulNotifiedValue, // stores the notified value
portMAX_DELAY); // wait forever
if (xResult == pdPASS) { // if a notification is received
m5.Lcd.printf("button %d", ulNotifiedValue);
switch (ulNotifiedValue) { // to demonstrate the use of the switch statement
case 0:
ESP_LOGD(TAG, "button 0");
break;
case 1:
ESP_LOGD(TAG, "button 1");
break;
case 2:
ESP_LOGD(TAG, "button 2");
break;
default:
ESP_LOGD(TAG, "This should not happen...");
break;
}
}
}
vTaskDelete(NULL); // remove the task whene done
}
extern "C" void app_main() { // ESP32 FreeRTOS application entry point
ESP_LOGD(TAG, "Starting...");
gpio_config_t xButtonConfig;
xButtonConfig.pin_bit_mask = GPIO_SEL_37 | GPIO_SEL_38 | GPIO_SEL_39;
xButtonConfig.mode = GPIO_MODE_INPUT;
xButtonConfig.pull_up_en = GPIO_PULLUP_DISABLE;
xButtonConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
xButtonConfig.intr_type = GPIO_INTR_ANYEDGE;
gpio_config(&xButtonConfig);
m5.begin();
m5.Lcd.setTextSize(3);
xTaskCreatePinnedToCore(vfnButtonTask, // function with task's code
"Button task", // name
2048, // stack size
(void *) NULL, // input parameters
10, // priority
&xButtonHandle, // task handle (for callback from ISR)
1); // core to run on
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(GPIO_NUM_39, // GPIO to attach to
vfnButtonISR, // ISR to call
(void*) GPIO_NUM_39); // Parameters to pass
gpio_isr_handler_add(GPIO_NUM_38, vfnButtonISR, (void*) GPIO_NUM_38);
gpio_isr_handler_add(GPIO_NUM_37, vfnButtonISR, (void*) GPIO_NUM_37);
}
@egeltje
Copy link
Author

egeltje commented Dec 24, 2018

Note the different notation styles between FreeRTOS (Hungarian notation) and the M5 library (COBOL notation (kebab-case :-) ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment