Планировщик FreeRTOS, выполняющий переключение контекста для той же задачи

Я заметил странное поведение при отладке анализируемой системы. В системе есть три периодических задачи:

«Задача-1» с периодичностью 10 миллисекунд. Высокий приоритет.

«Задача-2» с периодичностью 10 миллисекунд. Средний приоритет.

«Задача-3» с периодичностью 10 миллисекунд. Низкий приоритет.

Содержание трех задач - это просто критическая секция, которая является общедоступной. Инверсия приоритетов происходит часто, и я заставляю эту ситуацию видеть, как система ведет себя во времени. Systick имеет период 1 мс.

Из того, что я читал о FreeRTOS, в Cortex-M изменение контекста задачи выполняется через ожидающий бит, который в сценарии периодических задач может быть активирован с помощью:

  1. Обработчик тикового таймера находит задачу с наивысшим приоритетом в очереди готовности и устанавливает ожидающий бит переключения контекста;

  2. В функции «vDelayTaskUntil», которая ожидает следующей активации;

  3. Когда семафор занят и задача, которая пытается его получить.

Тем не менее, я обнаружил такое поведение:

Иногда, когда задача с высоким приоритетом находится внутри семафора, переключение контекста происходит само, как описано ниже.

https://i.stack.imgur.com/j7aa9.png

Как уже отмечалось, задача 1 сама переключает контекст.

Вы знаете, как мне сказать, почему это происходит?

Прикрепляем код теста:

Задание 1:

void vTask1_handler(void *params) {
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 10;
    xLastWakeTime = xTaskGetTickCount();
    int i = 0, to =0;

for (;;) {
    vTaskDelayUntil(&xLastWakeTime, xFrequency);
    to = DWT->CYCCNT;
    for (i = 0; i < to % 500; i++);
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
        to = DWT->CYCCNT;
        for (i = 0; i < to % 5000; i++);
        xSemaphoreGive(xSemaphore);
    }

}
}

Задача-2:

void vTask2_handler(void *params) {
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 10;
    xLastWakeTime = xTaskGetTickCount();
    int i = 0, to = 0;

for (;;) {
    vTaskDelayUntil(&xLastWakeTime, xFrequency);
    to = DWT->CYCCNT;
    for (i = 0; i < to % 200; i++);
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
        to = DWT->CYCCNT;
        for (i = 0; i < to % 10000; i++);
        xSemaphoreGive(xSemaphore);
    }
}

Задача-3:

void vTask3_handler(void *params) {
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 10;
    xLastWakeTime = xTaskGetTickCount();
    int i = 0, to=0;

for (;;) {
    vTaskDelayUntil(&xLastWakeTime, xFrequency);
    to = DWT->CYCCNT;
    for (i = 0; i < to % 200; i++);
    if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
        to = DWT->CYCCNT;
        for (i = 0; i < to % 10000; i++);
        xSemaphoreGive(xSemaphore);
    }
}
}

Спасибо.


person Bruno Miranda    schedule 20.05.2020    source источник


Ответы (2)


Я подозреваю, что он идет к планировщику в вызове семафора семафоров, и делает вывод, что это все еще готовая задача с наивысшим приоритетом.

person Realtime Rik    schedule 21.05.2020

freertos имеет периодическое прерывание, которое при возникновении проверяет, пришло ли время разблокировать или разбудить задачу. Я думаю, что вы видите это прерывание.

см. https://www.freertos.org/implementation/a00011.html для получения подробной информации о прерывании тика.

вы также можете посмотреть https://www.freertos.org/low-power-tickless-rtos.html, если вы хотите отключить его при входе в задачу с низким энергопотреблением в режиме ожидания.

person arye    schedule 27.05.2020