Wake up a task from an ISR

Hey guys; hoping someone can help me with, what i believe to be a simple problem, but i’m stumped. i have a working sample that allows me to wake a task from another task via a handle and i would simply like to do the same thing from within an ISR. with the example below, I am able to trigger an interrupt from a task ( lighting the onboard led ), but i cannot get another task ( flash_led ) to run from the triggered ISR? what am i missing? using ESP32 DEV C.

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"

#define BLINK_GPIO      2
#define LED_FADE_GIPO   15
#define GIPO_0          18 /// INTTERRUPTOR ( SOURCE PIN )
#define GIPO_1          19 
#define INTERUPT_GPIO   25
#define DEBUG_TASK_STAC 2048

#define HEARTBEAT_DELAY     3000
#define HEARTBEAT_PULSE     100
#define HEARTBEAT_FLASH     200
#define NOTIFICATION_PAUSE  1000
#define INTERUPT_DELAY      5000

TaskHandle_t flashHandle = NULL;
TaskHandle_t xHandle;

void task_interuptPing(void *pvParameter) { 

    gpio_pad_select_gpio(GIPO_0);
    gpio_set_direction(GIPO_0, GPIO_MODE_OUTPUT);
    TaskHandle_t handle;
    //handle =  (TaskHandle_t*)pvParameter;


    while(1){

        gpio_set_level(GIPO_0, 1);
        vTaskDelay(HEARTBEAT_PULSE / portTICK_PERIOD_MS);

        gpio_set_level(GIPO_0, 0);
        vTaskDelay(INTERUPT_DELAY / portTICK_PERIOD_MS);

        //vTaskResume((TaskHandle_t*)pvParameter);
        //vTaskDelay(INTERUPT_DELAY / portTICK_PERIOD_MS);
    }

}

void task_flashLED(void *pvParameter) { 

    gpio_pad_select_gpio(GIPO_1);
    gpio_set_direction(GIPO_1, GPIO_MODE_OUTPUT);

    while(1){
        printf("LED SUSPEND\r\n");
        vTaskSuspend(NULL);

        vTaskDelay(HEARTBEAT_PULSE / portTICK_PERIOD_MS);

        gpio_set_level(GIPO_1, 1);
        vTaskDelay(HEARTBEAT_PULSE / portTICK_PERIOD_MS);

        gpio_set_level(GIPO_1, 0);

    }

}

void handler( void *args ){
    BaseType_t xHigherPriorityTaskWoken;
    uint32_t ulStatusRegister = 0x00;
    TaskHandle_t handle;

     handle =  (TaskHandle_t*)args;
    
        if (gpio_get_level(BLINK_GPIO)){
		    gpio_set_level(BLINK_GPIO, 0); 
	    }else{
		    gpio_set_level(BLINK_GPIO, 1); 
	    }

    xHigherPriorityTaskWoken = pdFALSE;

    xTaskNotifyFromISR(handle, 0, ulStatusRegister,&xHigherPriorityTaskWoken );

    ///vTaskNotifyGiveFromISR(handle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR();
}


void app_main() {

    setvbuf(stdout, NULL, _IONBF, 0); // SECURED BUFF FIX FOR PRINTF

    gpio_pad_select_gpio(BLINK_GPIO);
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_INPUT_OUTPUT); // SETTING TO READ AND SET?!?!

    xTaskCreate( &task_flashLED, "flashLED", DEBUG_TASK_STAC, NULL, 7, &flashHandle);
    //xTaskCreate( &task_interuptPing, "Task 1", DEBUG_TASK_STAC, (void*)pcTextForTask1, 1, NULL );
    xTaskCreate( &task_interuptPing, "Task 1", DEBUG_TASK_STAC, (void*)flashHandle, 1, NULL );

    // INTERRUPTT /////
    gpio_config_t gpioConfig;
        gpioConfig.pin_bit_mask = GPIO_SEL_25;
        gpioConfig.mode         = GPIO_MODE_INPUT;
        gpioConfig.pull_up_en   = GPIO_PULLUP_DISABLE;
        gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
        gpioConfig.intr_type    = GPIO_INTR_POSEDGE;

    gpio_config(&gpioConfig); // config pin 25 for interupts.
    gpio_install_isr_service(0);
    gpio_isr_handler_add(INTERUPT_GPIO, &handler, (void*)flashHandle);


}

If I understand this correctly you are creating a task implemented by task_flashLED(), storing the task’s handle in flashHandle, then passing flashHandle as the context for an interrupt implemented by handler(). The interrupt then uses the task handle in a call to xTaskNotifyFromISR to send a notification to the task. I would therefore expect task_flashLED() to be blocked on the notification sent to it from the interrupt, but at no place does task_flashLED() block on a notification using https://www.freertos.org/ulTaskNotifyTake.html or https://www.freertos.org/xTaskNotifyWait.html.

Can you copy the scheme demonstrated in the code snippets on this page to get it to work: https://www.freertos.org/RTOS_Task_Notification_As_Counting_Semaphore.html

Hi Richard, thank you for replying so quickly. As you describe: however, I do suspend the task.

vTaskSuspend(NULL);

Inside the flash_led task. My assumption is that notifyFromISR would behave the same way it does in the non-ISR versions? I can wake the task up periodically using another task? Does it not behave this way? What am I missing?

Notify waits up a TaskNotifyTake or TaskNotifyWait. Suspend needs a Resume. They are different mechanisms.

Your assumption is right that xTaskNotifyFromISR behaves like the task level function.
Like Richard I wonder why you don’t use xTaskNotifyWait as the matching counterpart to wait for the notification resp. getting woken up from blocked state by the ISR.
That’s the right way of doing ISR to task synchronization. Better don’t (ab)use vTaskSuspend/Resume for task synchronization. These are kind of special functions for different purposes.

Oh, excellent! Thank you guys for explaining the differences; really appreciate it.