/* GPIO Example
https://www.programmersought.com/article/7556268640/
https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/
https://techtutorialsx.com/2017/09/30/esp32-arduino-external-interrupts/
https://www.lucadentella.it/en/2017/02/25/esp32-12-io-e-interrupts/
https://github.com/lucadentella/esp32-tutorial/blob/master/07_gpio_interrupts/main/main.c
https://techtutorialsx.com/2017/05/06/esp32-arduino-creating-a-task/
https://savjee.be/2020/01/multitasking-esp32-arduino-freertos/
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#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 "freertos/semphr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
// This TaskHandle will allow
TaskHandle_t task1Handle = NULL;
/**
Brief:
This test code shows how to configure gpio and how to use gpio interrupt.
GPIO status:
GPIO18: output
GPIO19: output
GPIO4: input, pulled up, interrupt from rising edge and falling edge
GPIO5: input, pulled up, interrupt from rising edge.
Test:
Connect GPIO18 with GPIO4
Connect GPIO19 with GPIO5
Generate pulses on GPIO18/19, that triggers interrupt on GPIO4/5
*/
#define CONFIG_LED_PIN GPIO_NUM_13
#define GPIO_OUTPUT_IO_0 GPIO_NUM_18
#define GPIO_OUTPUT_IO_1 GPIO_NUM_19
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0 GPIO_NUM_4
#define GPIO_INPUT_IO_1 GPIO_NUM_2
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
#define ESP_INTR_FLAG_DEFAULT 0
SemaphoreHandle_t xSemaphore = NULL;
bool led_status = false;
static xQueueHandle gpio_evt_queue = NULL;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
// notify the button task
////////// xSemaphoreGiveFromISR(xSemaphore, NULL);
}
static void gpio_task_example(void* arg)
{
uint32_t io_num;
for (;;) {
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level((gpio_num_t)io_num));
}
}
}
// task that will react to button clicks
void button_task(void* arg) {
printf("Button always in pressed!\n");
// infinite loop
for (;;) {
printf("Button always in look pressed!\n");
// wait for the notification from the ISR
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
printf("Button pressed!\n");
led_status = !led_status;
gpio_set_level(CONFIG_LED_PIN, led_status);
}
}
}
// task that will react to button clicks
void Task1(void* arg) {
printf("Button task1 always in pressed!\n");
// infinite loop
int cnt = 0;
for (;;) {
led_status = !led_status;
gpio_set_level(CONFIG_LED_PIN, led_status);
// int cnt = 0;
// while (1) {
printf("cnt: %d\n", cnt++);
vTaskDelay(1000 / portTICK_RATE_MS);
//vTaskDelay(500 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
// vTaskDelete( NULL );
}
}
void anotherTask(void * parameter) {
// Kill task1 if it's running
if (task1Handle != NULL) {
vTaskDelete(task1Handle);
}
}
void setup()
{
gpio_config_t io_conf;
//disable interrupt
io_conf.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_DISABLE;
//set as output mode
io_conf.mode = GPIO_MODE_OUTPUT;
//bit mask of the pins that you want to set,e.g.GPIO18/19
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
//disable pull-down mode
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; //0;
//disable pull-up mode
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; // 0;
//configure GPIO with the given settings
gpio_config(&io_conf);
//interrupt of rising edge
io_conf.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_POSEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // 1;
gpio_config(&io_conf);
//change gpio intrrupt type for one pin
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
//Create Semaphore
xSemaphore = xSemaphoreCreateBinary();
xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
//remove isr handler for gpio number.
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//create tasks in cores testing
xTaskCreate(Task1, "Task1", 2048, NULL, 1, &task1Handle );
}
void loop()
{
delay(1000);
/*
int cnt = 0;
while (1) {
printf("cnt: %d\n", cnt++);
vTaskDelay(1000 / portTICK_RATE_MS);
gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
}
*/
}
/*
void IRAM_ATTR isr_lane(void* arg){
uint32_t gpio_num = (uint32_t) arg;
Serial.println( gpio_num );
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
uint8_t pin = 8;
gpio_config_t io_conf;
io_conf.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_DISABLE;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
//io_conf.pin_bit_mask = 0B00000000000000001000000000000000; //works for pin 15
//io_conf.pin_bit_mask = 0B00000000000000000000000000001000; //works for pin 8
io_conf.pin_bit_mask = 0B00000000000000000000000100000000; //should work for pin 8
io_conf.mode = GPIO_MODE_INPUT;
gpio_config(&io_conf);
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_HIGH_LEVEL);
gpio_install_isr_service(0);
gpio_isr_handler_add((gpio_num_t)pin, isr_lane, (void*) pin);
}
------------------
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#define GPIO_4 4
#define ESP_INTR_FLAG_DEFAULT 0 // Interrupt flag bit
static xQueueHandle gpio_evt_queue = NULL;
void gpio_task1(void)
{
for (int i = 5; i > 0; i--)
{
printf("task1: %d\n", i);
vTaskDelay(500 / portTICK_RATE_MS);
}
return;
}
void gpio_task2(void)
{
for (int i = 5; i > 0; i--)
{
printf("task2: %d\n", i);
vTaskDelay(500 / portTICK_RATE_MS);
}
return;
}
void gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void gpio_task_example(void* arg)
{
for( ;; )
{
// Task code goes here.
uint32_t io_num;
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)
{
// GPIO1
gpio_config_t io_conf = {}; // The new configuration GPIO pad Of gpio_config Structure of functional parameters
io_conf.pin_bit_mask = (1ULL << GPIO_4); // Set up GPIO4 The mask of is 1
io_conf.mode = GPIO_MODE_INPUT; // Set up GPIO4 For output mode
io_conf.pull_up_en = 1; // Pull up
io_conf.pull_down_en = 0; // No pull down
io_conf.intr_type = GPIO_INTR_POSEDGE; //GPIO4 The rising edge triggers the interrupt
if (gpio_config(&io_conf) == ESP_OK) // To configure GPIO4
printf("gpio4_config succeed \n");
else
printf("gpio4_config failed \n");
if (gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT) == ESP_OK) // Set interrupt service
printf("gpio_install_isr_service succeed \n");
else
printf("gpio_install_isr_service failed \n");
if (gpio_isr_handler_add(GPIO_4, gpio_isr_handler, (void*)GPIO_4 ) == ESP_OK) // Set interrupt handler
printf("gpio_isr_handler_add succeed \n");
else
printf("gpio_isr_handler_add failed \n");
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
while(1)
{
gpio_task1();
gpio_task2();
}
}
*/