Unblock and Run Multiple Tasks from Interrupt

Hi Forum,
Just joining you here. Got a how-do-I-do-this for dummies question. I’m writing an application that fires a GPIO interrupt. I’ve got it to run one piece of code. I’m struggling to get it to fire off another Task.

I got the interrupt going by judicious and liberal use of copy and paste from an example library. So no credit goes tome for that. It uses the int_signal_handler. I was trying to get another task to run using xTaskNotifyGive(testTaskHandle) or the FromISR version of that. But both cause a kernal panic. Everything breaks. Clearly something critically wrong with my code!

Here’s the jist of it.

void testTask(void *pvParameter);
TaskHandle_t testTaskHandle = NULL;
TaskHandle_t lis3dhTaskHandle = NULL;


void app_main()
{
    user_init();  
    xTaskCreate(&testTask, "TestTask", 1028, NULL, tskIDLE_PRIORITY + 5, &testTaskHandle ); 
}


void testTask(void *pvParameter) 
{
    ESP_LOGI(TAG, "TestTask: Starting");

    while (1)
    {
        ESP_LOGI(TAG, "TestTask: Executing... ");
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    }
}


void user_task_interrupt (void *pvParameters)
{
    ...

    while (1)
    {
        if (xQueueReceive(gpio_evt_queue, &gpio_num, portMAX_DELAY))
	{
	    do interrupt stuff!
	}
    }
}


static void IRAM_ATTR int_signal_handler (void* arg)        // Needed to change from IRAM to IRAM_ATTR
{
    uint32_t gpio_num = (uint32_t) arg;
    // send an event with GPIO to the interrupt user task
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);

    // xTaskNotifyGive(testTaskHandle);

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(testTaskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(  );
}


void user_init(void)
{
    ... blah
    gpio_isr_handler_add(INT1_PIN, int_signal_handler, (void*) INT1_PIN	);
    ... blah
    xTaskCreate(user_task_interrupt, "user_task_interrupt", TASK_STACK_DEPTH, NULL, 2, &lis3dhTaskHandle);
}

user_task_interrupt executes fine. I’m trying to add another Task, testTask for now, as a wireframe into which I’ll copy another working task. Would love it if someone more experienced could give me a few pointers. Apologies if it’s an overly simple question.

Anyway, loving FreeRTOS. Thanks all.

Al.

The ‘&testTask’ looks wrong here, you shouldn’t use the ‘&’ and just pass ‘testTask’.

This would have to be the ‘FromISR’ version as it is inside an interrupt, but I think you know that.

I’m not familiar with the ESP32 version of FreeRTOS (it is not a port we created ourselves but a lot of people use it) so I’m not sure of the fine details - but might be able to help if you can post any output that is generated when the panic occurs.

A trick that I have found useful for debugging Task Notifications is to check for strays before and after the section where I expect to be getting notifications:

	/* Ensure this task does not already have a notification pending by calling
	 ulTaskNotifyTake() with the xClearCountOnExit parameter set to pdTRUE, and a block time of 0
	 (don't block). */
	rc = ulTaskNotifyTake(pdTRUE, 0);
	configASSERT(!rc);
 
   // Something gets kicked off.
  // ...

   // I expect a notification to arrive soon.
    // Wait for notification from ISR:
     rc = ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(timeOut)); 
    // ...

	// There should be no more notifications pending:
	configASSERT(!ulTaskNotifyTake(pdTRUE, 0));        

Doing this has “unmasked” some interrupt masking problems for me.

@rtel Hero’s work! Thanks. It all sprung to life like magic. I had a play using both the ISR and non-iSR version sending the notification from inside the ISR handler and the task it calls. Both work perfectly. FreeRTOS is making me very happy!

Thanks for the tip @carlk3. I’ll give that a whirl to try and keep on top of any problems.

Cheers,

Al.

I have tested code that has multiple task notifications per task now - once I’ve updated the docs in task.h I will create a PR to bring it into the github repo.

2 Likes