FreeRTOS任务无限期阻塞而没有上下文切换。

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

FreeRTOS task blocks indefinitely without context switch

问题

我正在编写一个简单的FreeRTOS应用程序,在其中我创建一个新任务并阻塞,直到新任务已初始化。但是,在命中信号量阻塞后,任务永远不会继续运行。看看这个:

main.cpp

#include "thread2.hpp"
os2::thread2 th{};

extern "C" auto app_main() -> void {
    vTaskDelay(portMAX_DELAY);
};

thread2.hpp

#include <cstdio>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

namespace os2
{

    struct comm_obj
    {
        SemaphoreHandle_t sem;
    };

    inline auto worker(void* const param) -> void
    {
        printf("Worker task before giving mux");
        fflush(stdout);

        auto& comm = *static_cast<comm_obj*>(param);

        xSemaphoreGive(comm.sem);

        printf("Worker after giving mux!\n");
        fflush(stdout);

        vTaskDelete(NULL);
    }

    struct thread2
    {

        thread2() {

            printf("init!\n");
            StaticSemaphore_t stack;

            comm_obj comm{
                .sem = xSemaphoreCreateBinaryStatic(&stack),
            };

            printf("Hello ");
            fflush(stdout);
            [[maybe_unused]] TaskHandle_t handle = xTaskCreateStaticPinnedToCore(
                &worker,
                "default",
                5*1024,
                &comm,
                10,
                stack_.data(),
                &tcb_,
                0);

            printf("World!");
            fflush(stdout);
            xSemaphoreTake(comm.sem, portMAX_DELAY);
        }

        StaticTask_t tcb_;
        std::array<StackType_t, 5*1024> stack_;
    };

}

这只会输出:

init!
Hello World!

(然后停滞,触发任务看门狗)

但是工作任务从未被调用。似乎程序正在阻塞在xSemaphoreTake(comm.sem, portMAX_DELAY);上,但在这种情况下,任务应该屈服,新创建的任务应该开始运行(如果我的逻辑正确的话)。为什么会发生这种情况呢?

英文:

I'm writing a simple FreeRTOS app in which I create a new task and block until the new task has been initialized. However, the task never proceeds to run after hitting the semaphore block. Check this out:

main.cpp

#include &quot;thread2.hpp&quot;
os2::thread2 th{};

extern &quot;C&quot; auto app_main() -&gt; void {
    vTaskDelay(portMAX_DELAY);
};

thread2.hpp

#include &lt;cstdio&gt;

#include &quot;freertos/FreeRTOS.h&quot;
#include &quot;freertos/task.h&quot;
#include &quot;freertos/semphr.h&quot;

namespace os2
{

    struct comm_obj
    {
        SemaphoreHandle_t sem;
    };

    inline auto worker(void* const param) -&gt; void
    {
        printf(&quot;Worker task before giving mux&quot;);
        fflush(stdout);

        auto&amp; comm = *static_cast&lt;comm_obj*&gt;(param);

        xSemaphoreGive( comm.sem );

        printf(&quot;Worker after giving mux!\n&quot;);
        fflush(stdout);

        vTaskDelete(NULL);
    }

    struct thread2
    {

        thread2() {

            printf(&quot;init!\n&quot;);
            StaticSemaphore_t stack;

            comm_obj comm{
                .sem = xSemaphoreCreateBinaryStatic(&amp;stack),
            };

            printf(&quot;Hello &quot;);
            fflush(stdout);
            [[maybe_unused]] TaskHandle_t handle = xTaskCreateStaticPinnedToCore(
                &amp;worker,
                &quot;default&quot;,
                5*1024,
                &amp;comm,
                10,
                stack_.data(),
                &amp;tcb_,
                0);

            printf(&quot;World!&quot;);
            fflush(stdout);
            xSemaphoreTake( comm.sem, portMAX_DELAY );
        }

        StaticTask_t tcb_;
        std::array&lt;StackType_t, 5*1024&gt; stack_;
    };

}

This will just output:

init!
Hello World!

(and then stall which causes the task watchdog to be triggered)

But the worker task is never called. It seems that the program is blocking on xSemaphoreTake( comm.sem, portMAX_DELAY ); but in this case the task should yield and the newly created task should start to run (if my logic is correct). Why is that not happening?

答案1

得分: 1

问题在于任务调度器从未有机会启动,因为线程对象是静态初始化的,而这发生在调度程序启动之前。因此,当构造函数运行时,它立即触发信号量阻塞,之后的一切都无法执行,因为在这个阶段没有多线程。

英文:

The problem was that the task scheduler never had a chance to start as the thread object is statically initialized which happens before the scheduler is started. So when the constructor is run it immediately hits the semaphore block and everything after that can't ever be executed because there is no multithreading at this stage.

huangapple
  • 本文由 发表于 2023年3月7日 19:18:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75661307.html
匿名

发表评论

匿名网友

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

确定