vTaskSuspendAll on Core0 halt tasks on Core1 too

andreykorol
Posts: 5
Joined: Thu Jul 20, 2017 6:04 am

vTaskSuspendAll on Core0 halt tasks on Core1 too

Postby andreykorol » Fri Aug 18, 2017 9:06 am

As i understood (and see at sources) calling vTaskSuspendAll must suspend tasks just on current core, but it also stops tasks on Core1.
Is this right behavior?

Test example on ESP32 Core Board V2 (ESP-wroom-32) - just keep pressed button and task on core1 stops print.

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_task_wdt.h"

#define BTN_GPIO				0

void Task0(void * data) {
	printf("Task0: start on CORE%u\n", xPortGetCoreID());
	while(1){
		printf("Task0\n");
		fflush(stdout);
		if (!gpio_get_level(BTN_GPIO)) {
			printf("Task0 - call \"vTaskSuspendAll\" on Core%u\n", xPortGetCoreID());
			fflush(stdout);
			vTaskSuspendAll();
			while (!gpio_get_level(BTN_GPIO)) {
				esp_task_wdt_feed();
			}
			xTaskResumeAll();
			printf("Task0 - call \"xTaskResumeAll\" on Core%u\n", xPortGetCoreID());
			fflush(stdout);
		}
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

void Task1(void * data) {
	printf("Task1: start on CORE%u\n", xPortGetCoreID());
	while(1){
		printf("Task1\n");
		fflush(stdout);
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

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

	gpio_config_t io_conf;
	io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
	io_conf.mode = GPIO_MODE_INPUT;
	io_conf.pin_bit_mask = (1 << BTN_GPIO);
	io_conf.pull_down_en = 0;
	io_conf.pull_up_en = 0;
	gpio_config(&io_conf);
	
	xTaskCreatePinnedToCore(Task0, "Task0", 2048, NULL, (configMAX_PRIORITIES - 1), NULL, 0);
	xTaskCreatePinnedToCore(Task1, "Task1", 2048, NULL, (configMAX_PRIORITIES - 1), NULL, 1);
}
But if we will call vTaskSuspendAll on core1 all works as suspected - tasks on core0 keep works

ESP_igrr
Posts: 2072
Joined: Tue Dec 01, 2015 8:37 am

Re: vTaskSuspendAll on Core0 halt tasks on Core1 too

Postby ESP_igrr » Fri Aug 18, 2017 11:23 am

I think the story here is that the tick interrupt on Core0 updates the global tick count. vTaskSuspendAll disables tick count updates, and as such, tasks sitting in vTaskDelay on Core1 never start running, because tick count remains constant.

Thanks for pointing out this problem. Maybe we need to improve the logic used for updating the tick count so that the behaviour is at least symmetrical.

At the same time, please note that in real applications it is not advisable to suspend tasks on core 0 for any significant amount of time, as this may affect operation of wifi and tcp/ip stacks.

meowsqueak
Posts: 151
Joined: Thu Jun 15, 2017 4:54 am
Location: New Zealand

Re: vTaskSuspendAll on Core0 halt tasks on Core1 too

Postby meowsqueak » Sun Sep 03, 2017 11:58 pm

I'm not sure if it's related, but I'm calling vTaskSuspendAll() to ensure no task switch while in the middle of a timing-sensitive GPIO bit-bash routine (followed by xTaskResumeAll()), and the LWIP stack continues to run (so is presumably running on the other CPU) but then asserts:

Code: Select all

    components/freertos/./queue.c:1442 (xQueueGenericReceive)- assert failed!

    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
In my case the GPIO function actually doesn't mind if the other CPU continues to run as long as its own CPU is not task switched. However it seems that the LWIP stack isn't so happy with this arrangement.

Who is online

Users browsing this forum: Google [Bot] and 99 guests