[SOLVED] Subtask does not trigger Watchdog

leschge
Posts: 37
Joined: Fri May 06, 2022 1:38 pm

[SOLVED] Subtask does not trigger Watchdog

Postby leschge » Thu Dec 14, 2023 9:54 am

Hey, I am struggling a bit to understand when a watchdog is caused and when not.
I created the following example program, with 3 tasks. Task A runs on core 1 and task C runs on core 0. Now task A schedules a subtask B with a while loop.
In my understanding, this should cause a watchdog reset, but does not. However, when I remove task C from core 0, I do get a watchdog. What's the explanation for this?

Additional question:
Is it possible to have a subtask B that runs for example 10 seconds without feeding the watchdog or using vTaskDelay? (as it magically seem to do now)
The other task should still be executed on both cores. The parent task A would eventually force stop task B if it runs longer than 30 seconds.

Code: Select all

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define CORE_0 0
#define CORE_1 1

#define TASK_SIZE 2048

static StackType_t StackA[TASK_SIZE] = {0};
static StackType_t StackB[TASK_SIZE] = {0};
static StackType_t StackC[TASK_SIZE] = {0};

static StaticTask_t TaskA;
static StaticTask_t TaskB;
static StaticTask_t TaskC;

TaskHandle_t taskHandle_A;
TaskHandle_t taskHandle_B;
TaskHandle_t taskHandle_C;

void taskARunnabe(void* args);
void taskBRunnabe(void* args);
void taskCRunnabe(void* args);

static int createdTaskB = 0;

void app_main(void)
{
    printf("Hello world!\n");

    printf("Starting Task C!\n");
    taskHandle_C = xTaskCreateStaticPinnedToCore(taskCRunnabe, "TaskC", TASK_SIZE, NULL, 2, StackC, &TaskC, CORE_0);
    if(!taskHandle_C)
    {
        printf("Starting Task C Failed!\n");
    }

    printf("Starting Task A!\n");
    taskHandle_A = xTaskCreateStaticPinnedToCore(taskARunnabe, "TaskA", TASK_SIZE, NULL, 2, StackA, &TaskA, CORE_1);
    if(!taskHandle_A)
    {
            printf("Starting Task A Failed!\n");
    }
}


void taskCRunnabe(void* args)
{
	while(1){
		printf("TaskC\n");
		vTaskDelay(10); // Avoid Task watchdog for Task C
	};

	printf("End Task C!\n");
}

void taskARunnabe(void* args)
{
	//while(1){}; //Causes Task watchdog as expected

	while(1){
		if(createdTaskB == 0)
		{
			createdTaskB = 1;
			printf("Starting Task B!\n");
			taskHandle_B = xTaskCreateStaticPinnedToCore(taskBRunnabe, "TaskB", TASK_SIZE, NULL, 1, StackB, &TaskB, CORE_1);

			if(!taskHandle_B)
			{
				printf("Starting Task B Failed!\n");
			}
		}

		vTaskDelay(10); // Avoid Task watchdog for Task A

		printf("TaskA\n");
	}

	printf("End Task A!\n");
}


void taskBRunnabe(void* args)
{
	while(1){
		printf("TaskB\n");
	};

	printf("End Task B!\n");
}
Last edited by leschge on Fri Dec 15, 2023 12:48 pm, edited 1 time in total.

MicroController
Posts: 1708
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Subtask does not trigger Watchdog

Postby MicroController » Thu Dec 14, 2023 12:42 pm

By default, only FreeRTOS's IDLE task is registered with a watchdog, and there's the "interrupt watchdog".
The watchdogs will stay quiet as long as
1. you don't register additional tasks with the watchdog,
2. the IDLE task gets a chance to run at least briefly every few (5?) seconds, and
3. FreeRTOS's preemption/task switching is not inhibited for longer than the interrupt watchdog's timeout (default: 300ms, I believe)

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Subtask does not trigger Watchdog

Postby ESP_Sprite » Thu Dec 14, 2023 12:50 pm

Oooh, this is a lovely question, thanks, I actually needed to think about this a bit.
leschge wrote:
Thu Dec 14, 2023 9:54 am
Hey, I am struggling a bit to understand when a watchdog is caused and when not.
I created the following example program, with 3 tasks. Task A runs on core 1 and task C runs on core 0. Now task A schedules a subtask B with a while loop.
Few nitpicks here. First of all, it *creates* the task, not schedules it. Secondly, there is no such thing as a 'subtask'. xTaskCreateWhatever() tells the FreeRTOS kernel to create a task and the task created is entirely independent from whatever task called the function to create it.
In my understanding, this should cause a watchdog reset, but does not. However, when I remove task C from core 0, I do get a watchdog. What's the explanation for this?
With 'get a watchdog', I imagine you mean a task watchdog timeout? A task watchdog timeout normally happens when an idle task doesn't get to run for a predetermined amount of time, usually because some other task is hogging the CPU without calling any blocking APIs. In your example, task B looks like it does that.

I'm going to put the explanation below, select the region of text to view it, but I'm going to give you some hints first as you seem to like figuring stuff out yourself.
- 1. What happens when you remove the printf("TaskC\n") and/or printf("TaskB\n")
- 2. Even if task B and task C are running simultaneously, you never see their printfs interfering with eachother. That is done on purpose as interfering printfs makes debugging harder. Can you think about how that could have an effect on what you're seeing?

Solution here, select text to view:
The trick here, however, is that you have two tasks running printf() statements (namely task B and C). Printfs actually can block: if not you could have two tasks that run concurrently on the two cores print the text 'through eachother', i.e. rather than 'Task B' and 'Task C' you'd get 'TTaasskk BC'. To stop that from happening, there's a mux somewhere down the logic that is called by printf() that waits if the other core is in the process of printing something. That 'wait' de-schedules the task and allows the idle task to run, and as such you won't get a task watchdog timeout.
If you run the tasks on the same core, there's no risk of them interfering, so the mux code is never called and tasks won't 'wait': that core is always busy printing either task B's or task C's text, and as such the idle task won't run and the watchdog will bite.

Additional question:
Is it possible to have a subtask B that runs for example 10 seconds without feeding the watchdog or using vTaskDelay? (as it magically seem to do now)

The other task should still be executed on both cores. The parent task A would eventually force stop task B if it runs longer than 30 seconds.
It shouldn't be possible to have a task run without calling a blocking function for longer than the task watchdog timeout is set for. You'd either need to increase the watchdog timeout or call a blocking function somewhere.

leschge
Posts: 37
Joined: Fri May 06, 2022 1:38 pm

Re: Subtask does not trigger Watchdog

Postby leschge » Fri Dec 15, 2023 12:47 pm

Thanks to both of you, that helped a lot. And great to see that my questions bring some joy haha.
I don't know why haven't thought of printf() needs to be blocking / thread safe, as I actually implemented something similar a while ago ...

Who is online

Users browsing this forum: No registered users and 108 guests