Skip to content

Instantly share code, notes, and snippets.

@igrr
Forked from ermacv/esp32c3_gpio_interrupt.c
Created May 3, 2022 18:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igrr/5c4617b99d3cfa840cb88feeb3b58bff to your computer and use it in GitHub Desktop.
Save igrr/5c4617b99d3cfa840cb88feeb3b58bff to your computer and use it in GitHub Desktop.
Code to reproduce "interrupt is not triggered during the light sleep" on ESP32-C3 (updated)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_pm.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "esp_intr_alloc.h"
// LED pin info
#define LED_PIN 2
#define LED_PIN_MSK (1ULL<<LED_PIN)
// Button pin info
#define BUTTON_PIN 9
#define BUTTON_PIN_MSK (1ULL<<BUTTON_PIN)
// Interrupt flags
#define ESP_INTR_FLAG_DEFAULT 0
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR gpio_isr_handler(void* arg) {
uint32_t gpio_num = (uint32_t) arg;
int in_level = gpio_get_level(gpio_num);
if (in_level == 0) {
gpio_set_intr_type(gpio_num, GPIO_INTR_HIGH_LEVEL);
} else {
gpio_set_intr_type(gpio_num, GPIO_INTR_LOW_LEVEL);
}
// On any GPIO interrupt send the data using queue
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
// And toggle the LED gpio
static uint32_t level = 0;
gpio_set_level(LED_PIN, level);
level = level ? 0 : 1;
portYIELD_FROM_ISR();
}
static void gpio_task_example(void* arg) {
uint32_t io_num;
for(;;) {
// Try to receive data from the ISR
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num));
}
}
}
void app_main(void) {
esp_err_t err;
// Init LED GPIO
static const gpio_config_t led_cfg= {
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = LED_PIN_MSK,
};
err = gpio_config(&led_cfg);
assert(err == ESP_OK);
// Init button GPIO
static const gpio_config_t button_cfg = {
.intr_type = GPIO_INTR_LOW_LEVEL,
.pin_bit_mask = BUTTON_PIN_MSK,
.mode = GPIO_MODE_INPUT,
};
err = gpio_config(&button_cfg);
assert(err == ESP_OK);
// Create queue and task to process GPIO ISR events
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
assert(gpio_evt_queue);
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
// Enable button GPIO interrupt
err = gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
assert(err == ESP_OK);
err = gpio_isr_handler_add(BUTTON_PIN, gpio_isr_handler, (void*) BUTTON_PIN);
assert(err == ESP_OK);
// Enable power manager
static const esp_pm_config_esp32c3_t pm_config = {
.max_freq_mhz = 80,
.min_freq_mhz = 80,
.light_sleep_enable = true,
};
err = esp_pm_configure(&pm_config);
assert(err == ESP_OK);
esp_sleep_enable_gpio_wakeup();
gpio_wakeup_enable(BUTTON_PIN, GPIO_INTR_LOW_LEVEL);
// Block current task forever
vTaskDelay(portMAX_DELAY);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment