Как синхронизировать c поток, используя мьютекс в freeRTOS? - PullRequest
1 голос
/ 11 апреля 2020

У меня есть код, написанный на freeRTOS, мне нужно добиться синхронизации мьютекса, чтобы не было параллелизма, но я столкнулся с одной проблемой:

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();
    }
}

проблема с кодом - я получение вывода

[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

<- </p>

Как вы можете видеть, задача 1 выполняется дважды и после этой задачи 2 выполняется дважды, что не является идеальным выводом, я ожидаю, идеальный вывод должен чередоваться между task1 и task2.

Я нашел одну статью, которая достигает такого поведения, link , но это предлагает повозиться с ядром freeRTOS. Я ищу альтернативное решение. Любая помощь приветствуется.

Спасибо и всего наилучшего

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Поскольку эти две задачи имеют одинаковый приоритет, вполне приемлемо, что они ждут друг друга в течение периода времени, когда они будут работать только в течение периода времени (потому что они будут только запланированы в устройстве!) - это не ошибка, а особенность!

Приобретение мьютекса, выполнение действия (выходной вызов в вашем примере кода) и возврат мьютекса, очевидно, занимает намного меньше, чем период выборки (по крайней мере, с вашей текущей (нулевой?) Нагрузкой других задач / ISRs) .

Поэтому мы должны рассмотреть, почему вы хотите, чтобы они точно чередовались. Если вы хотите, чтобы периоды доступа к общему ресурсу планировались «одинаково», возможно, стоит выяснить, будет ли этого достаточно если они имеют одинаковое количество назначений мьютекса в течение определенного более длительного периода (т. е. совместного использования пятьдесят на пятьдесят, но не чередующегося назначения). (и до этого) task2 (по какой-то причине, исходящей из вашего приложения), возможно, лучше планируйте реализовать «жетоноподобный» дизайн, в котором каждая задача явно запускает другую (например, используя одно событие в каждом направлении, но пропуская текущий мьютекс). Эта схема также будет работать стабильно, если вы создадите дополнительную нагрузку на систему вокруг пары задач - в то время как существующий дизайн mutex + delay потребует переналадки каждый раз, когда меняется ситуация с нагрузкой вокруг ваших двух задач.

0 голосов
/ 12 апреля 2020

Что если пропустить задержку (после освобождения мьютекса)? Я думаю, вы увидите желаемое переключение поведения. Я мог бы себе представить, что, например, если task1 все еще спит после освобождения мьютекса, task2 заканчивает вывод достаточно быстро (в течение 1 тикового периода) и также засыпает. Так что задержка истекает для обеих задач в одно и то же время. Поскольку обе задачи имеют одинаковый приоритет, планировщик абсолютно свободен для запуска любой задачи.

...