如何在freeRTOS中使用互斥锁来同步线程? [英] How to sync thread using mutex in freeRTOS?

查看:144
本文介绍了如何在freeRTOS中使用互斥锁来同步线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段用 freeRTOS 编写的代码,我必须实现互斥锁同步才能不发生并发,但我一直面临一个问题:

xSemaphoreHandle xMutex=NULL;无效 fn_test1(){int i=0;同时(1){xSemaphoreTake(xMutex,portMAX_DELAY);ESP_LOGI(TAG, "Task1 output = %d", i++);xSemaphoreGive(xMutex);vTaskDelay(10);}}void fn_test2(){int i=0;同时(1){xSemaphoreTake(xMutex,portMAX_DELAY);ESP_LOGI(TAG, "Task2 output = %d", i++);xSemaphoreGive(xMutex);vTaskDelay(10);}}void app_main(){字符任务名称[16];ESP_ERROR_CHECK(nvs_flash_init());//初始化_wifi();//wait_for_ip();xMutex=xSemaphoreCreateMutex();//xMutex 将在没有创建 Mutex 时存储 NULL如果(xMutex!=NULL){xTaskCreate(fn_test1,"task1",4096,NULL,1,NULL);xTaskCreate(fn_test2,"task2",4096,NULL,1,NULL);//vTaskStartScheduler();}}

代码的问题是我正在获取输出

[0;32mI (40) 示例:Task1 输出 = 0[0m[0;32mI (50) 示例:Task2 输出 = 0[0m[0;32mI (547) 示例:Task2 输出 = 1[0m[0;32mI (547) 示例:Task1 输出 = 1[0m[0;32mI (647) 示例:Task2 输出 = 2[0m[0;32mI (647) 示例:Task1 输出 = 2[0m

-->

<块引用>

[0;32mI (747) 示例:Task1 输出 = 3[0m[0;32mI (747) 示例:Task2 输出 = 3[0m[0;32mI (847) 示例:Task2 输出 = 4[0m[0;32mI (847) 示例:Task1 输出 = 4[0m[0;32mI (947) 示例:Task1 输出 = 5[0m

<--

如您所见,task1 执行了两次,然后 task2 执行了两次,这不是我期望的理想输出,理想的输出应该在 task1 和 task2 之间交替.

我发现了一篇实现这种行为的文章,link,但它建议修补 freeRTOS 内核.我寻求替代解决方案.任何帮助表示赞赏.

感谢和问候

解决方案

由于这两个任务具有相同的优先级,因此它们相互等待长达一个系统提示周期是可以接受的行为(因为它们只会在systick!)-这不是错误,而是一个功能!

获取互斥锁、执行操作(示例代码中的输出调用)并返回互斥锁显然比系统提示周期短得多(至少,在您当前(零?)负载被其他任务/ISR 加载的情况下.

>

因此,我们应该考虑为什么您希望它们完全交替.如果您只希望共享资源的访问周期被平等地"安排,那么可能值得研究一下,如果它们在某个更长的时间段(即 550共享,但不是交替分配).相反,如果 要求为什么必须在 task2 之后(和之前)处理 task2(出于某种来自您的应用程序的原因),那么实施类令牌"可能是一个更好的计划" 设计,其中每个任务显式触发另一个任务(例如,每个方向使用一个事件,但省略当前互斥锁).如果您在这对任务周围创建一些额外的系统负载,这种设计也将表现稳定 - 而当前的互斥体+延迟设计将需要在每次您的两个任务周围的负载情况发生变化时重新调整.

I have a code written in freeRTOS, I have to achieve mutex synchronisation so that concurrency doesn't occur, but I have been facing one issue:

xSemaphoreHandle xMutex=NULL;

void fn_test1()
{
    int i=0;
    while(1)
    {

        xSemaphoreTake(xMutex,portMAX_DELAY );
        ESP_LOGI(TAG, "Task1 output = %d", i++);
        xSemaphoreGive(xMutex);
        vTaskDelay(10);
    }
}   
void fn_test2()
{
    int i=0;
    while(1)
    {
        xSemaphoreTake(xMutex,portMAX_DELAY );
        ESP_LOGI(TAG, "Task2 output = %d", i++);
        xSemaphoreGive(xMutex);
        vTaskDelay(10);
    }
}   

void app_main()
{
    char task_name[16];
    ESP_ERROR_CHECK( nvs_flash_init() );
    // initialise_wifi();
    // wait_for_ip();
    xMutex=xSemaphoreCreateMutex();  //xMutex will be storing NULL when Mutex not created
    if(xMutex!=NULL) {
        xTaskCreate(fn_test1,"task1",4096,NULL,1,NULL);
        xTaskCreate(fn_test2,"task2",4096,NULL,1,NULL);
        //vTaskStartScheduler();
    }
}

the problem with the code is i am getting output

[0;32mI (40) example: Task1 output = 0[0m
[0;32mI (50) example: Task2 output = 0[0m
[0;32mI (547) example: Task2 output = 1[0m
[0;32mI (547) example: Task1 output = 1[0m
[0;32mI (647) example: Task2 output = 2[0m
[0;32mI (647) example: Task1 output = 2[0m

-->

[0;32mI (747) example: Task1 output = 3[0m
[0;32mI (747) example: Task2 output = 3[0m
[0;32mI (847) example: Task2 output = 4[0m
[0;32mI (847) example: Task1 output = 4[0m
[0;32mI (947) example: Task1 output = 5[0m

<--

As you can see task1 is executed twice and after that task2 is executed twice, which is not the ideal output I expect, the ideal output should be alternating between task1 and task2.

I found one article that achieves such a behaviour, link, but it suggests to tinker with freeRTOS kernel. I seek an alternate solution. Any help is appreciated.

Thanks and regards

解决方案

As these two tasks have equal priority, it is acceptable behaviour that they wait for each other for up to a systick period (because they will only be scheduled in the systick!) - this is not a bug, but a feature!

Acquiring the mutex, doing the action (output call in your example code) and returning the mutex apparently takes much less than a systick period (at least, with your present (zero?) load by other tasks/ISRs.

Therefore, we should consider why you want them to be exactly alternating. If you only want access periods to the shared resource to be scheduled "equally", it might be worth to investigate whether it would also be sufficient if they have an equal number of mutex assignments during a certain, longer period (i.e., fifty-fifty sharing, but not an alternating assignment). If, conversely, there is a requirement why task2 must be processed after (and before) task2 (for some reason that comes from your application), it might be a better plan to implement a "token-like" design, where each task triggers the other one explicitly (e. g., using one event per direction, but omitting the current mutex). This design would also behave stable if you create some additional system load around the pair of tasks - while the present mutex+delay design will require readjustment every time the load situation around your two tasks changes.

这篇关于如何在freeRTOS中使用互斥锁来同步线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆