From 5a2c1abf800277b78aff8be741608ba1f534649d Mon Sep 17 00:00:00 2001 From: Jon Enz Date: Tue, 14 Oct 2025 13:40:48 -0500 Subject: [PATCH 1/2] Update the FreeRTOS Kernel. --- FreeRTOS-Kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeRTOS-Kernel b/FreeRTOS-Kernel index dbf7055..0adc196 160000 --- a/FreeRTOS-Kernel +++ b/FreeRTOS-Kernel @@ -1 +1 @@ -Subproject commit dbf70559b27d39c1fdb68dfb9a32140b6a6777a0 +Subproject commit 0adc196d4bd52a2d91102b525b0aafc1e14a2386 From 003c4de996d9cc1bb390c07ec559df7e7805b79b Mon Sep 17 00:00:00 2001 From: Jon Enz Date: Tue, 14 Oct 2025 13:42:46 -0500 Subject: [PATCH 2/2] Change 'FreeRTOS::Task::delay' to be public. Add a static option for 'FreeRTOS::Task::delayUntil' --- FreeRTOS-Cpp/include/FreeRTOS/Task.hpp | 127 +++++++++++++++++-------- examples/Task/delay.cpp | 9 ++ examples/Task/delayUntil.cpp | 24 +++++ 3 files changed, 120 insertions(+), 40 deletions(-) diff --git a/FreeRTOS-Cpp/include/FreeRTOS/Task.hpp b/FreeRTOS-Cpp/include/FreeRTOS/Task.hpp index d74fc3d..792b99a 100644 --- a/FreeRTOS-Cpp/include/FreeRTOS/Task.hpp +++ b/FreeRTOS-Cpp/include/FreeRTOS/Task.hpp @@ -112,6 +112,93 @@ class TaskBase { taskFunction(); }; +#if (INCLUDE_vTaskDelay == 1) + /** + * Task.hpp + * + * @brief Function that calls void vTaskDelay( const TickType_t + * xTicksToDelay ) + * + * @see + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task for a given number of ticks. The actual time that the task + * remains blocked depends on the tick rate. The constant portTICK_PERIOD_MS + * can be used to calculate real time from the tick rate - with the resolution + * of one tick period. + * + * delay() specifies a time at which the task wishes to unblock relative to + * the time at which delay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after delay() + * is called. delay() does not therefore provide a good method of controlling + * the frequency of a periodic task as the path taken through the code, as + * well as other task and interrupt activity, will affect the frequency at + * which delay() gets called and therefore the time at which the task next + * executes. See delayUntil() for an alternative API function designed to + * facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task + * should unblock. + * + * @param ticksToDelay The amount of time, in tick periods, that the task + * should block. + * + * Example Usage + * @include Task/delay.cpp + */ + inline static void delay(const TickType_t ticksToDelay = 0) { + vTaskDelay(ticksToDelay); + } +#endif /* INCLUDE_vTaskDelay */ + +#if (INCLUDE_xTaskDelayUntil == 1) + /** + * Task.hpp + * + * @brief Function that calls BaseType_t xTaskDelayUntil( TickType_t + * *pxPreviousWakeTime, const TickType_t xTimeIncrement ) + * + * @see + * + * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * This function differs from delay() in one important aspect: delay() will + * cause a task to block for the specified number of ticks from the time delay + * () is called. It is therefore difficult to use delay() by itself to + * generate a fixed execution frequency as the time between a task starting to + * execute and that task calling delay() may not be fixed [the task may take a + * different path though the code between calls, or may get interrupted or + * preempted a different number of times each time it executes]. + * + * Whereas delay() specifies a wake time relative to the time at which the + * function is called, delayUntil() specifies the absolute (exact) time at + * which it wishes to unblock. + * + * The function pdMS_TO_TICKS() can be used to calculate the number of ticks + * from a time specified in milliseconds with a resolution of one tick period. + * + * @param timeIncrement The cycle time period. The task will be unblocked at + * time (previousWakeTime + timeIncrement). Calling delayUntil() with the same + * timeIncrement parameter value will cause the task to execute with a fixed + * interval period. + * @return true If the task way delayed. + * @return false Otherwise. A task will not be delayed if the next expected + * wake time is in the past. + * + * Example Usage + * @include Task/delayUntil.cpp + */ + inline static bool delayUntil(TaskBase& task, + const TickType_t timeIncrement = 0) { + return (xTaskDelayUntil(&task.previousWakeTime, timeIncrement) == pdTRUE); + } +#endif /* INCLUDE_xTaskDelayUntil */ + #if (INCLUDE_uxTaskPriorityGet == 1) /** * Task.hpp @@ -1124,46 +1211,6 @@ class TaskBase { */ virtual void taskFunction() = 0; -#if (INCLUDE_vTaskDelay == 1) - /** - * Task.hpp - * - * @brief Function that calls void vTaskDelay( const TickType_t - * xTicksToDelay ) - * - * @see - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Delay a task for a given number of ticks. The actual time that the task - * remains blocked depends on the tick rate. The constant portTICK_PERIOD_MS - * can be used to calculate real time from the tick rate - with the resolution - * of one tick period. - * - * delay() specifies a time at which the task wishes to unblock relative to - * the time at which delay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after delay() - * is called. delay() does not therefore provide a good method of controlling - * the frequency of a periodic task as the path taken through the code, as - * well as other task and interrupt activity, will affect the frequency at - * which delay() gets called and therefore the time at which the task next - * executes. See delayUntil() for an alternative API function designed to - * facilitate fixed frequency execution. It does this by specifying an - * absolute time (rather than a relative time) at which the calling task - * should unblock. - * - * @param ticksToDelay The amount of time, in tick periods, that the task - * should block. - * - * Example Usage - * @include Task/delay.cpp - */ - inline static void delay(const TickType_t ticksToDelay = 0) { - vTaskDelay(ticksToDelay); - } -#endif /* INCLUDE_vTaskDelay */ - #if (INCLUDE_xTaskDelayUntil == 1) /** * Task.hpp diff --git a/examples/Task/delay.cpp b/examples/Task/delay.cpp index 25e6c4d..9b05c8d 100644 --- a/examples/Task/delay.cpp +++ b/examples/Task/delay.cpp @@ -18,3 +18,12 @@ void MyTask::taskFunction() { delay(xDelay); } } + +class MyDriverClass { + public: + void doSomething() { + // Some driver code that will delay the calling task for 100ms. + constexpr TickType_t xDelay = 100 / portTICK_PERIOD_MS; + FreeRTOS::Task::delay(xDelay); + } +}; diff --git a/examples/Task/delayUntil.cpp b/examples/Task/delayUntil.cpp index 533b734..96b0188 100644 --- a/examples/Task/delayUntil.cpp +++ b/examples/Task/delayUntil.cpp @@ -5,6 +5,14 @@ class MyTask : public FreeRTOS::Task { void taskFunction() final; }; +class MyDifferentTask : public FreeRTOS::Task { + public: + void taskFunction() final; +}; + +MyTask myTask; +MyDifferentTask myDifferentTask; + void MyTask::taskFunction() { // Perform an action every 10 ticks. constexpr TickType_t xFrequency = 10; @@ -20,3 +28,19 @@ void MyTask::taskFunction() { } } } + +void MyDifferentTask::taskFunction() { + // Perform an action every 20 ticks. + constexpr TickType_t xFrequency = 20; + + for (;;) { + // Wait for the next cycle. + auto wasDelayed = FreeRTOS::Task::delayUntil(myTask, xFrequency); + + // Perform action here. wasDelayed value can be used to determine + // whether a deadline was missed if the code here took too long. + if (wasDelayed) { + // Check for deadline miss. + } + } +}