vTaskCreatePinnedToCore() 没有按预期行为

huangapple go评论67阅读模式
英文:

vTaskCreatePinnedToCore() isn't behaving as expected

问题

我正在使用ESP-IDF,并希望在ESP32的不同内核上同时运行两个任务,所以我使用了以下代码:
xTaskCreatePinnedToCore(sensorsTask, "Sensor", 5000, 0, 0, &sensorTaskHandler, 0); xTaskCreatePinnedToCore(storageTask, "Storage", 5000, 0, 0, &storageTaskHandler, 1);
相应的任务是:

void storageTask(){
    for(;;){
        gpio_set_level(4, 1);
        gpio_set_level(2, 0);
    }
}

void sensorsTask(){
    for(;;){
        gpio_set_level(2, 1);
        gpio_set_level(4, 0);
    }
}

如果两个任务真正并行运行,那么两个LED应该一直亮着,但实际上两个LED在闪烁,这意味着两个任务是依次运行的。即"SensorTask"首先在内核0上运行,然后"storageTask"在内核1上运行。
现在,如果我们在两个任务中都添加vTaskDelay(1),它能正常运行。但问题是,如果两个任务真的同时独立运行,为什么LED会闪烁,为什么需要添加延迟。请记住,这种延迟实际上有助于在任务之间切换,但在这种情况下,我们有两个内核和两个任务,因此实际上不需要切换。我试图在ESP-32的两个内核上同时运行两个任务,但感觉它们是依次运行的,就像在单核微控制器上一样。

英文:

I was working with ESP-IDF and I want to run two task at the same time of different cores of ESP32, So I used
xTaskCreatePinnedToCore(sensorsTask, "Sensor" , 5000, 0, 0, &sensorTaskHandler,0);
xTaskCreatePinnedToCore(storageTask, "Storage", 5000, 0, 0, &storageTaskHandler,1);

and the corrosponding tasks are:

`void storageTask(){
for(;;){
	gpio_set_level(4, 1);
	gpio_set_level(2, 0);
}
}


void sensorsTask(){
for(;;){
	gpio_set_level(2, 1);
	gpio_set_level(4, 0);
}
}`

if both tasks are running really parallel then both LEDs should be ON all the time, but in real Both LEDs were flickering, which mean that both task are running one by one. i-e "SensorTask" runs on core 0 first **THEN **"storageTask" runs on core 1.
Now if we add vTaskDelay(1) in both tasks it works fine, but the question is if both tasks are running simultaneously and independent of each other then why LEDs were flickering, and what is the need of adding delay. keeping the thing in mind that this delay actually help to switch b/w tasks, but in this case we have two cores and two task so no switching is really required.

I am trying to run two tasks on two cores of ESP-32 at the same time but its feels that they are running one by one as in single core microcontrollers

答案1

得分: 2

你已创建了 2 个优先级为 0 的任务,这是系统中最低的优先级。ESP IDF 隐式创建了若干其他任务(许多具有较高优先级),你的任务必须与这些任务共享 CPU 核心。

首先有 2 个空闲任务(每个核心一个)的优先级为 0。由于你的任务和空闲任务的优先级相同,它们平等地共享核心时间(50/50)。因此,调度程序默认每 10 毫秒在每个核心上轮流切换它们,这很可能是导致你闪烁问题的根源。

接下来有其他更高优先级的任务,ESP IDF 创建这些任务。如果你启用了 WiFi,则其驱动程序在高优先级(默认为 23)的任务中运行。高分辨率定时器服务创建其自己的高优先级(22)任务。如果你启用了 TCP/IP 网络,它在高优先级任务中运行;等等。可以肯定地说,如果你不使用它们的服务,这些任务不会占用太多核心时间。但它们确实占用了一些时间。

总而言之,你不能独占一个 CPU 核心。你可以通过提高你的优先级来削减空闲任务(顺便说一下,如果你根本不让空闲任务运行,任务看门狗定时器会很快报警并重置系统;除非你将其禁用)。你还可以通过将你的优先级提高到最大来剔除所有其他任务,但在任何真正的嵌入式系统中,这些其他任务都会做一些有用的事情 vTaskCreatePinnedToCore() 没有按预期行为

英文:

You have created 2 tasks with priority 0 which is the lowest priority in the system. ESP IDF implicitly creates a several other tasks (many with higher priorities) and your tasks have to share CPU cores with those.

Firstly there are 2 idle tasks (one per core) with priority 0. Since the priorities of your tasks and the idle tasks are equal, they share core time equally (50/50). So the scheduler rotates them on each core every 10 ms by default, which is quite likely the source of your flickering.

Then there are other, higher priority tasks which ESP IDF creates. If you enabled WiFi then its driver runs in a high priority (23 by default) task. The High Resolution Timer service creates its own high priority (22) task. If you've enabled TCP/IP networking, this has runs in a high priority task; etc. Granted, those tasks don't take up much core time if you don't use their services. But they take up some.

So, in short you don't get exclusive use of a CPU core. You can cut out the idle tasks by raising your priority (by the way, the Task Watchdog Timer will complain and reset the system soon if you don't let the idle task run at all; unless you disable it). You can also cut out all other tasks by raising your priority to the maximum, but in any real embedded system those other tasks do something useful vTaskCreatePinnedToCore() 没有按预期行为

答案2

得分: 0

可能与ESP32是SMP有关。

https://www.freertos.org/single-core-amp-smp-rtos-scheduling.html

不能100%确定,但FreeRTOS任务调度器需要在某个地方运行,它只会在一个核心上运行,随后会停止两个任务,因为它要弄清楚该做什么。因此,它必须在一个核心上暂停其中一个任务。如果没有延迟,那么调度器可能会遇到问题。

这只是一个猜测,可能会指导你朝正确的方向前进。

英文:

Might be to do with the fact that ESP32 is SMP.

https://www.freertos.org/single-core-amp-smp-rtos-scheduling.html

Not 100% sure but the Freertos task scheduler needs to run somewhere, it will only run on 1 core, subsequently stopping both tasks as it figures out what to do. So it will have to pause one of the task on a core. Without the delay then the scheduler may struggle.

This is a bit of guess. Might point you in the right direction.

huangapple
  • 本文由 发表于 2023年5月29日 04:54:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76353561.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定