1

我有一份工作应该以 5 秒的最小间隔运行。启动此作业的触发器可以在任何时刻以任何频率执行。

在 RTOS 环境中解决这种情况的最佳方法是什么?

如果它不存在,我想创建一个创建任务的函数。现有任务在做任何事情之前应该等待最小时间间隔过去。在等待时,应该创建它的函数应该跳过新任务的创建。

检查任务是否已创建但尚未完成的正确方法是什么?在这种情况下我应该使用任务吗?

下面的代码示例:

#define CONFIG_MIN_INTERVAL 5000

uint32_t last_execution_timestamp = 0;
TaskHandle_t *task_handle = NULL;
bool task_done = true;

static void report_task(void *context)
{
    if (esp_timer_get_time() / 1000 < last_execution_timestamp + CONFIG_MIN_INTERVAL)
    {
        ESP_LOGI(stateTAG, "need to wait for  for right time");
        int time_to_wait = last_execution_timestamp + CONFIG_MIN_INTERVAL - esp_timer_get_time() / 1000;
        vTaskDelay(time_to_wait / portTICK_PERIOD_MS);
    }

    // do something...

    task_done = true;
    vTaskDelete(task_handle);
}

void init_report_task(uint32_t context)
{    
    if (!task_done)
    {
        ESP_LOGI(stateTAG, "TASK already exists");
    }
    else
    {
        ESP_LOGI(stateTAG, "Creating task");
        xTaskCreate(&report_task, "report_task", 8192, (void *)context, 4, task_handle);
        task_done = false;
    }
}
4

1 回答 1

4

eTaskGetState可用于检查任务是否已在运行,但这样的解决方案可能容易受到竞争的影响。例如,您的任务在技术上仍在“运行”,而实际上它正在“完成”,即设置task_done = true;和准备退出。

更好的解决方案可能是使用队列(或信号量)并让任务连续运行,等待消息到达并循环处理它们。

使用信号量,您可以xSemaphoreTake(sem, 5000 / portTICK_PERIOD_MS);等待唤醒条件或 5 秒的超时,以先到者为准。

== 编辑 ==

如果没有事件任务应该等待。只有当事件发生时,它才应该运行该作业。如果过去 5 秒内没有执行,它应该立即运行它。如果有执行,它应该等到自上次执行后 5 秒,然后才运行它

您可以通过仔细管理信号量等待的滴答声来实现这一点。像这样的东西(未经测试):

TickType_t nextDelay = portMAX_DELAY;
TickType_t lastWakeup = 0;
const TickType_t minDelay = 5000 / portTICK_PERIOD_MS;

for (;;) {
    bool signalled = xSemaphoreTake(sem, nextDelay);
    TickType_t now = (TickType_t)(esp_timer_get_time() / (portTICK_PERIOD_MS * 1000));
    if (signalled) {
        TickType_t ticksSinceLastWakeup = now - lastWakeup;
        if (ticksSinceLastWakeup < minDelay) {
            // wakeup too soon - schedule next wakeup and go back to sleep
            nextDelay = minDelay - ticksSinceLastWakeup;
            continue;
        }
    }
    lastWakeup = now;
    nextDelay = portMAX_DELAY;
    
    // do work ...
}
于 2021-02-13T11:17:38.033 回答