freertos/Demo/Common/include/FreeRTOS/Task.hpp

1484 lines
62 KiB
C++
Raw Normal View History

2024-07-13 16:33:13 +00:00
/*
* FreeRTOS-Cpp
* Copyright (C) 2021 Jon Enz. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* https://github.com/jonenz/FreeRTOS-Cpp
*/
#ifndef FREERTOS_TASK_HPP
#define FREERTOS_TASK_HPP
#include <FreeRTOS/Kernel.hpp>
#include <bitset>
#include <utility>
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "event_groups.h"
#include "semphr.h"
/**
* @brief C function that is used to interface this class with the FreeRTOS
* kernel.
*
* @note This function should not be called or referenced by the user.
*
* @param task Pointer to an instance of FreeRTOS::TaskBase.
*/
void callTaskFunction(void* task);
namespace FreeRTOS {
/**
* @class TaskBase Task.hpp <FreeRTOS/Task.hpp>
*
* @brief Base class that provides the standard task interface to FreeRTOS::Task
* and FreeRTOS::StaticTask.
*
* @note This class is not intended to be instantiated or derived from by the
* user. Use FreeRTOS::Task or FreeRTOS::StaticTask as a base class for a user
* implemented task.
*/
class TaskBase {
public:
friend class Task;
template <UBaseType_t>
friend class StaticTask;
TaskBase(const TaskBase&) = delete;
TaskBase& operator=(const TaskBase&) = delete;
static void* operator new(size_t, void* ptr) { return ptr; }
static void* operator new[](size_t, void* ptr) { return ptr; }
static void* operator new(size_t) = delete;
static void* operator new[](size_t) = delete;
enum class State {
Running = eRunning,
Ready = eReady,
Blocked = eBlocked,
Suspended = eSuspended,
Deleted = eDeleted,
// Invalid = eInvalid,
};
enum class NotifyAction {
NoAction = eNoAction,
SetBits = eSetBits,
Increment = eIncrement,
SetValueWithOverwrite = eSetValueWithOverwrite,
SetValueWithoutOverwrite = eSetValueWithoutOverwrite,
};
// NOLINTNEXTLINE
using NotificationBits = std::bitset<32>;
/**
* Task.hpp
*
* @brief Function that acts as the entry point of the task instance. This
* function initializes the previous wake time of the task and calls the user
* implemented taskFunction().
*
* @note This function is only public so that it can be accessed by the C
* interface function <tt>callTaskFunction()</tt> and should not be called or
* referenced by the user.
*/
virtual inline void taskEntry() final {
previousWakeTime = FreeRTOS::Kernel::getTickCount();
taskFunction();
};
#if (INCLUDE_uxTaskPriorityGet == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>UBaseType_t uxTaskPriorityGet( TaskHandle_t
* xTask )</tt>
*
* @see <https://www.freertos.org/a00128.html>
*
* INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be
* available. See the RTOS Configuration documentation for more information.
*
* Obtain the priority of any task.
*
* @return UBaseType_t The priority of the task.
*
* <b>Example Usage</b>
* @include Task/getPriority.cpp
*/
inline UBaseType_t getPriority() const { return uxTaskPriorityGet(handle); }
#endif /* INCLUDE_uxTaskPriorityGet */
#if (INCLUDE_vTaskPrioritySet == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskPrioritySet( TaskHandle_t xTask,
* UBaseType_t uxNewPriority )</tt>
*
* @see <https://www.freertos.org/a00129.html>
*
* INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be
* available. See the configuration section for more information.
*
* Set the priority of the task.
*
* A context switch will occur before the function returns if the priority
* being set is higher than the currently executing task.
*
* @param newPriority The priority to which the task will be set.
*
* <b>Example Usage</b>
* @include Task/setPriority.cpp
*/
inline void setPriority(const UBaseType_t newPriority) const {
vTaskPrioritySet(handle, newPriority);
}
#endif /* INCLUDE_vTaskPrioritySet */
#if (INCLUDE_vTaskSuspend == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskSuspend( TaskHandle_t
* xTaskToSuspend )</tt>
*
* @see <https://www.freertos.org/a00130.html>
*
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be
* available. See the RTOS Configuration documentation for more information.
*
* Suspend a task. When suspended a task will never get any microcontroller
* processing time, no matter what its priority.
*
* Calls to suspend() are not accumulative - i.e. calling suspend() twice on
* the same task still only requires one call to resume() to ready the
* suspended task.
*
* <b>Example Usage</b>
* @include Task/suspend.cpp
*/
inline void suspend() const { vTaskSuspend(handle); }
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskResume( TaskHandle_t xTaskToResume
* )</tt>
*
* @see <https://www.freertos.org/a00131.html>
*
* INCLUDE_vTaskSuspend must be defined as 1 for this function to be
* available. See the RTOS Configuration documentation for more information.
*
* Resumes a suspended task.
*
* A task that has been suspended by one or more calls to suspend() will be
* made available for running again by a single call to resume().
*
* <b>Example Usage</b>
* @include Task/resume.cpp
*/
inline void resume() const { vTaskResume(handle); }
#if (INCLUDE_xTaskResumeFromISR == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskResumeFromISR( TaskHandle_t
* xTaskToResume )</tt>
*
* @see <https://www.freertos.org/taskresumefromisr.html>
*
* INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
* available. See the configuration section for more information.
*
* An implementation of resume() that can be called from within an ISR.
*
* A task that has been suspended by one or more calls to suspend() will be
* made available for running again by a single call to resumeFromISR().
*
* resumeFromISR() should not be used to synchronize a task with an interrupt
* if there is a chance that the interrupt could arrive prior to the task
* being suspended - as this can lead to interrupts being missed. Use of a
* semaphore as a synchronisation mechanism would avoid this eventuality.
*
* @retval true If resuming the task should result in a context switch. This
* is used by the ISR to determine if a context switch may be required
* following the ISR.
* @retval false Otherwise.
*
* <b>Example Usage</b>
* @include Task/resumeFromISR.cpp
*/
inline bool resumeFromISR() const {
return (xTaskResumeFromISR(handle) == pdTRUE);
}
#endif /* INCLUDE_xTaskResumeFromISR */
#endif /* INCLUDE_vTaskSuspend */
#if (INCLUDE_xTaskAbortDelay == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskAbortDelay( TaskHandle_t
* xTask )</tt>
*
* @see <https://www.freertos.org/xTaskAbortDelay.html>
*
* INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
* function to be available.
*
* A task will enter the Blocked state when it is waiting for an event. The
* event it is waiting for can be a temporal event (waiting for a time), such
* as when delay() is called, or an event on an object, such as when
* FreeRTOS::Queue::receive() or notifyTake() is called. If the handle of a
* task that is in the Blocked state is used in a call to abortDelay() then
* the task will leave the Blocked state, and return from whichever function
* call placed the task into the Blocked state.
*
* There is no 'FromISR' version of this function as an interrupt would need
* to know which object a task was blocked on in order to know which actions
* to take. For example, if the task was blocked on a queue the interrupt
* handler would then need to know if the queue was locked.
*
* @retval true Otherwise.
* @retval false If the task was not in the Blocked state.
*/
inline bool abortDelay() const { return (xTaskAbortDelay(handle) == pdPASS); }
#endif /* INCLUDE_xTaskAbortDelay */
#if (INCLUDE_xTaskGetIdleTaskHandle == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>TaskHandle_t xTaskGetIdleTaskHandle( void
* )</tt>
*
* @see <https://www.freertos.org/a00021.html#xTaskGetIdleTaskHandle>
*
* getIdleTaskHandle() is only available if INCLUDE_xTaskGetIdleTaskHandle is
* set to 1 in FreeRTOSConfig.h.
*
* Simply returns the handle of the idle task. It is not valid to call
* getIdleTaskHandle() before the scheduler has been started.
*
* @return TaskHandle_t The task handle associated with the Idle task. The
* Idle task is created automatically when the RTOS scheduler is started.
*/
inline static TaskHandle_t getIdleHandle() {
return xTaskGetIdleTaskHandle();
}
#endif /* INCLUDE_xTaskGetIdleTaskHandle */
#if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>UBaseType_t uxTaskGetStackHighWaterMark(
* TaskHandle_t xTask )</tt>
*
* @see <https://www.freertos.org/uxTaskGetStackHighWaterMark.html>
*
* INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h
* for this function to be available.
*
* Returns the high water mark of the stack. That is, the minimum free stack
* space there has been (in words, so on a 32 bit machine a value of 1 means 4
* bytes) since the task started. The smaller the returned number the closer
* the task has come to overflowing its stack.
*
* getStackHighWaterMark() and getStackHighWaterMark2() are the same except
* for their return type. Using configSTACK_DEPTH_TYPE allows the user to
* determine the return type. It gets around the problem of the value
* overflowing on 8-bit types without breaking backward compatibility for
* applications that expect an 8-bit return type.
*
* @return BaseType_t The smallest amount of free stack space there has been
* (in words, so actual spaces on the stack rather than bytes) since the task
* was created.
*/
inline UBaseType_t getStackHighWaterMark() const {
return uxTaskGetStackHighWaterMark(handle);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>UBaseType_t uxTaskGetStackHighWaterMark2(
* TaskHandle_t xTask )</tt>
*
* @see <https://www.freertos.org/uxTaskGetStackHighWaterMark.html>
*
* Returns the high water mark of the stack. That is, the minimum free stack
* space there has been (in words, so on a 32 bit machine a value of 1 means 4
* bytes) since the task started. The smaller the returned number the closer
* the task has come to overflowing its stack.
*
* getStackHighWaterMark() and getStackHighWaterMark2() are the same except
* for their return type. Using configSTACK_DEPTH_TYPE allows the user to
* determine the return type. It gets around the problem of the value
* overflowing on 8-bit types without breaking backward compatibility for
* applications that expect an 8-bit return type.
*
* @return configSTACK_DEPTH_TYPE The smallest amount of free stack space
* there has been (in words, so actual spaces on the stack rather than bytes)
* since the task was created.
*/
inline configSTACK_DEPTH_TYPE getStackHighWaterMark2() const {
return uxTaskGetStackHighWaterMark2(handle);
}
#endif /* INCLUDE_uxTaskGetStackHighWaterMark */
#if (INCLUDE_eTaskGetState == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>UBaseType_t uxTaskGetStackHighWaterMark2(
* TaskHandle_t xTask )</tt>
*
* @see <https://www.freertos.org/a00021.html#eTaskGetState>
*
* @see getInfo()
*
* INCLUDE_eTaskGetState must be defined as 1 for this function to be
* available. See the configuration section for more information.
*
* Obtain the state of any task. States are encoded by the
* FreeRTOS::Task::State enumerated class type.
*
* @return State The state of the task at the time the function was called.
* Note the state of the task might change between the function being called,
* and the functions return value being tested by the calling task.
*/
inline State getState() const {
return static_cast<State>(eTaskGetState(handle));
}
#endif /* INCLUDE_eTaskGetState */
/**
* Task.hpp
*
* @brief Function that calls <tt>char *pcTaskGetName( TaskHandle_t
* xTaskToQuery )</tt>
*
* @see <https://www.freertos.org/a00021.html#pcTaskGetName>
*
* Looks up the name of a task.
*
* @return const char* The text (human readable) name of the task. A pointer
* to the subject task's name, which is a standard NULL terminated C string.
*/
inline const char* getName() const { return pcTaskGetName(handle); }
#if (INCLUDE_xTaskGetHandle == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>TaskHandle_t xTaskGetHandle( const char
* *pcNameToQuery )</tt>
*
* @see <https://www.freertos.org/a00021.html#xTaskGetHandle>
*
* @note This function takes a relatively long time to complete and should be
* used sparingly.
*
* @param name The text name (as a standard C NULL terminated string) of the
* task for which the handle will be returned.
* @return TaskHandle_t The handle of the task that has the human readable
* name. NULL is returned if no matching name is found.
* INCLUDE_xTaskGetHandle must be set to 1 in FreeRTOSConfig.h for getHandle()
* to be available.
*/
inline static TaskHandle_t getHandle(const char* name) {
return xTaskGetHandle(name);
}
#endif /* INCLUDE_xTaskGetHandle */
#if (configUSE_TASK_NOTIFICATIONS == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskNotifyGiveIndexed(
* TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyGive.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each task has a private array of "notification values" (or
* 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
* The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
* indexes in the array, and (for backward compatibility) defaults to 1 if
* left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
* value per task.
*
* Events can be sent to a task using an intermediary object. Examples of
* such objects are queues, semaphores, mutexes and event groups. Task
* notifications are a method of sending an event directly to a task without
* the need for such an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment one of the task's notification values. In
* that way task notifications can be used to send data to a task, or be used
* as light weight and fast binary or counting semaphores.
*
* notifyGive() indicies is are intended for use when task notifications are
* used as light weight and faster binary or counting semaphore equivalents.
* Actual FreeRTOS semaphores are given using the FreeRTOS::Semaphore API, the
* equivalent action that instead uses a task notification is notifyGive().
*
* When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification
* using the notificationTake() API function rather than the
* notifyWaitIndexed() API function.
*
* @note Each notification within the array operates independently - a task
* can only block on one notification within the array at a time and will not
* be unblocked by a notification sent to any other array index.
*
* @param index The index within the target task's array of notification
* values to which the notification is to be sent. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* <b>Example Usage</b>
* @include Task/notifyGive.cpp
*/
inline void notifyGive(const UBaseType_t index = 0) const {
xTaskNotifyGiveIndexed(handle, index);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskNotifyGiveIndexedFromISR(
* TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t
* *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/vTaskNotifyGiveFromISR.html>
*
* Version of notifyGive() that can be used from an interrupt service routine
* (ISR). See the documentation page for the notifyGive() API function for a
* description of their operation and the necessary configuration parameters.
*
* @param higherPriorityTaskWoken A reference that will be set to true if
* sending the notification caused a task to unblock, and the unblocked task
* has a priority higher than the currently running task. If
* higherPriorityTaskWoken is set to true, then a context switch should be
* requested before the interrupt is exited.
* @param index The index within the target task's array of notification
* values to which the notification is to be sent. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* <b>Example Usage</b>
* @include Task/notifyGiveFromISR.cpp
*/
inline void notifyGiveFromISR(bool& higherPriorityTaskWoken,
const UBaseType_t index = 0) const {
BaseType_t taskWoken = pdFALSE;
vTaskNotifyGiveIndexedFromISR(handle, index, &taskWoken);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
}
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskNotifyGiveIndexedFromISR(
* TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t
* *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/vTaskNotifyGiveFromISR.html>
*
* @overload
*/
inline void notifyGiveFromISR(const UBaseType_t index = 0) const {
vTaskNotifyGiveIndexedFromISR(handle, index, NULL);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskNotifyIndexed( TaskHandle_t
* xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction
* eAction )</tt>
*
* @see <https://www.freertos.org/xTaskNotify.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each task has a private array of "notification values" (or
* 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
* The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
* indexes in the array, and (for backward compatibility) defaults to 1 if
* left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
* value per task.
*
* Events can be sent to a task using an intermediary object. Examples of
* such objects are queues, semaphores, mutexes and event groups. Task
* notifications are a method of sending an event directly to a task without
* the need for such an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment one of the task's notification values. In
* that way task notifications can be used to send data to a task, or be used
* as light weight and fast binary or counting semaphores.
*
* A task can use notifyWait() or notifyTake() to [optionally] block to wait
* for a notification to be pending. The task does not consume any CPU time
* while it is in the Blocked state.
*
* A notification sent to a task will remain pending until it is cleared by
* the task calling notifyWait() or notifyTake(). If the task was already in
* the Blocked state to wait for a notification when the notification arrives
* then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* @note Each notification within the array operates independently - a task
* can only block on one notification within the array at a time and will not
* be unblocked by a notification sent to any other array index.
*
* @param action Specifies how the notification updates the task's
* notification value, if at all. Valid values for action are as follows:
* <table> <tr><th>NotifyAction Setting <th>Action Performed
* <tr><td>NoAction <td>The target task receives the event,
* but its notification value is not updated. In this case value is not used.
* <tr><td>SetBits <td>The notification value of the target
* task will be bitwise ORed with value. For example, if value is set to 0x01,
* then bit 0 will get set within the target task's notification value.
* Likewise if value is 0x04 then bit 2 will get set in the target task's
* notification value. In this way the RTOS task notification mechanism can be
* used as a light weight alternative to an event group. <tr><td>Increment
* <td>The notification value of the target task will be incremented by one,
* making the call to notify() equivalent to a call to notifyGive(). In this
* case value is not used. <tr><td>SetValueWithOverwrite <td>The
* notification value of the target task is unconditionally set to value. In
* this way the RTOS task notification mechanism is being used as a light
* weight alternative to FreeRTOS::Queue::Overwrite().
* <tr><td>SetValueWithoutOverwrite <td>If the target task does not already
* have a notification pending then its notification value will be set to
* value. If the target task already has a notification pending then its
* notification value is not updated as to do so would overwrite the previous
* value before it was used. In this case the call to notify() fails and false
* is returned. In this way the RTOS task notification mechanism is being
* used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
* length 1.
* @param value Data that can be sent with the notification. How the data is
* used depends on the value of the action parameter.
* @param index The index within the target task's array of notification
* values to which the notification is to be sent. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @return false If action is set to SetValueWithoutOverwrite and the task's
* notification value cannot be updated because the target task already had a
* notification pending.
* @return true Otherwise.
*
* <b>Example Usage</b>
* @include Task/notify.cpp
*/
inline bool notify(const NotifyAction action,
const NotificationBits value = 0,
const UBaseType_t index = 0) const {
return (xTaskNotifyIndexed(handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action)) == pdPASS);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskNotifyAndQueryIndexed(
* TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
* eNotifyAction eAction, uint32_t *pulPreviousNotifyValue )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyAndQuery.html>
*
* notifyAndQuery() performs the same operation as notify() with the addition
* that it also returns the target task's prior notification value (the
* notification value at the time the function is called rather than when the
* function returns).
*
* @param action An enumerated type that can take one of the values documented
* in the table below in order to perform the associated action. <table>
* <tr><th>NotifyAction Setting <th>Action Performed
* <tr><td>NoAction <td>The target task receives the event,
* but its notification value is not updated. In this case value is not used.
* <tr><td>SetBits <td>The notification value of the target
* task will be bitwise ORed with value. For example, if value is set to 0x01,
* then bit 0 will get set within the target task's notification value.
* Likewise if value is 0x04 then bit 2 will get set in the target task's
* notification value. In this way the RTOS task notification mechanism can be
* used as a light weight alternative to an event group. <tr><td>Increment
* <td>The notification value of the target task will be incremented by one,
* making the call to notify() equivalent to a call to notifyGive(). In this
* case value is not used. <tr><td>SetValueWithOverwrite <td>The
* notification value of the target task is unconditionally set to value. In
* this way the RTOS task notification mechanism is being used as a light
* weight alternative to FreeRTOS::Queue::Overwrite().
* <tr><td>SetValueWithoutOverwrite <td>If the target task does not already
* have a notification pending then its notification value will be set to
* value. If the target task already has a notification pending then its
* notification value is not updated as to do so would overwrite the previous
* value before it was used. In this case the call to notify() fails and false
* is returned. In this way the RTOS task notification mechanism is being
* used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
* length 1.
* @param value Used to update the notification value of the task. See the
* description of the action parameter below.
* @param index The index within the target task's array of notification
* values to which the notification is to be sent. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @return false If action is set to SetValueWithoutOverwrite and the task's
* notification value cannot be updated because the target task already had a
* notification pending.
* @return true Otherwise.
*
* <b>Example Usage</b>
* @include Task/notifyAndQuery.cpp
*/
inline std::pair<bool, NotificationBits> notifyAndQuery(
const NotifyAction action, const NotificationBits value = 0,
const UBaseType_t index = 0) const {
uint32_t pulNotificationValue;
bool result =
(xTaskNotifyAndQueryIndexed(handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action),
&pulNotificationValue) == pdPASS);
return std::make_pair(result, NotificationBits(pulNotificationValue));
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t
xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,
* UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction,
uint32_t *pulPreviousNotifyValue,
* BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyAndQueryFromISR.html>
*
* notifyAndQueryFromISR() performs the same operation as notifyFromISR() with
the addition that it also returns the
* target task's prior notification value (the notification value at the time
the function is called rather than at
* the time the function returns).
* @param higherPriorityTaskWoken A reference that will be set to true if
sending the notification caused a task to
* unblock, and the unblocked task has a priority higher than the currently
running task. If higherPriorityTaskWoken
* is set to true, then a context switch should be requested before the
interrupt is exited.
* @param action An enumerated type that can take one of the values documented
in the table below in order to perform
* the associated action. <table>
* <tr><th>NotifyAction Setting <th>Action Performed
* <tr><td>NoAction <td>The target task receives the event,
but its notification value is not updated.
* In this case value is not used.
* <tr><td>SetBits <td>The notification value of the target
task will be bitwise ORed with value. For
* example, if value is set to 0x01, then bit 0 will get set within the target
task's notification value. Likewise if
* value is 0x04 then bit 2 will get set in the target task's notification
value. In this way the RTOS task
* notification mechanism can be used as a light weight alternative to an
event group.
* <tr><td>Increment <td>The notification value of the target
task will be incremented by one, making
* the call to notify() equivalent to a call to notifyGive(). In this case
value is not used.
* <tr><td>SetValueWithOverwrite <td>The notification value of the target
task is unconditionally set to value. In
* this way the RTOS task notification mechanism is being used as a light
weight alternative to
* FreeRTOS::Queue::Overwrite().
* <tr><td>SetValueWithoutOverwrite <td>If the target task does not already
have a notification pending then its
* notification value will be set to value. If the target task already has a
notification pending then its
* notification value is not updated as to do so would overwrite the previous
value before it was used. In this case
* the call to notify() fails and false is returned. In this way the RTOS
task notification mechanism is being used
* as a light weight alternative to FreeRTOS::Queue::send() on a queue of
length 1.
* @param value Used to update the notification value of the task. See the
description of the action parameter below.
* @param index The index within the target task's array of notification
values to which the notification is to be
* sent. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @retval false If action is set to SetValueWithoutOverwrite and the task's
notification value cannot be updated
* because the target task already had a notification pending.
* @retval true Otherwise.
* @return NotificationBits The task's notification value before any bits are
modified.
*
* <b>Example Usage</b>
* @include Task/notifyAndQueryFromISR.cpp
*/
inline std::pair<bool, NotificationBits> notifyAndQueryFromISR(
bool& higherPriorityTaskWoken, const NotifyAction action,
const NotificationBits value = 0, const UBaseType_t index = 0) const {
BaseType_t taskWoken = pdFALSE;
uint32_t pulNotificationValue;
bool result = (xTaskNotifyAndQueryIndexedFromISR(
handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action),
&pulNotificationValue, &taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return std::make_pair(result, NotificationBits(pulNotificationValue));
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t
xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,
* UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction,
uint32_t *pulPreviousNotifyValue,
* BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyAndQueryFromISR.html>
*
* @overload
*/
inline std::pair<bool, NotificationBits> notifyAndQueryFromISR(
const NotifyAction action, const NotificationBits value = 0,
const UBaseType_t index = 0) const {
uint32_t pulNotificationValue;
bool result = (xTaskNotifyAndQueryIndexedFromISR(
handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action),
&pulNotificationValue, NULL) == pdPASS);
return std::make_pair(result, NotificationBits(pulNotificationValue));
}
/**
* Task.hpp
*
* @brief Function that calls <tt> BaseType_t xTaskNotifyIndexedFromISR(
* TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
* eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyFromISR.html>
*
* Version of notify() that can be used from an interrupt service routine
* (ISR). See the documentation page for the notify() API function for a
* description of their operation and the necessary configuration parameters,
* as well as backward compatibility information.
*
* @param higherPriorityTaskWoken A reference that will be set to true if
* sending the notification caused a task to unblock, and the unblocked task
* has a priority higher than the currently running task. If
* higherPriorityTaskWoken is set to true, then a context switch should be
* requested before the interrupt is exited.
* @param action An enumerated type that can take one of the values documented
* in the table below in order to perform the associated action. <table>
* <tr><th>NotifyAction Setting <th>Action Performed
* <tr><td>NoAction <td>The target task receives the event,
* but its notification value is not updated. In this case value is not used.
* <tr><td>SetBits <td>The notification value of the target
* task will be bitwise ORed with value. For example, if value is set to 0x01,
* then bit 0 will get set within the target task's notification value.
* Likewise if value is 0x04 then bit 2 will get set in the target task's
* notification value. In this way the RTOS task notification mechanism can be
* used as a light weight alternative to an event group. <tr><td>Increment
* <td>The notification value of the target task will be incremented by one,
* making the call to notify() equivalent to a call to notifyGive(). In this
* case value is not used. <tr><td>SetValueWithOverwrite <td>The
* notification value of the target task is unconditionally set to value. In
* this way the RTOS task notification mechanism is being used as a light
* weight alternative to FreeRTOS::Queue::Overwrite().
* <tr><td>SetValueWithoutOverwrite <td>If the target task does not already
* have a notification pending then its notification value will be set to
* value. If the target task already has a notification pending then its
* notification value is not updated as to do so would overwrite the previous
* value before it was used. In this case the call to notify() fails and false
* is returned. In this way the RTOS task notification mechanism is being
* used as a light weight alternative to FreeRTOS::Queue::send() on a queue of
* length 1.
* @param value Used to update the notification value of the task. See the
* description of the action parameter below.
* @param index The index within the target task's array of notification
* values to which the notification is to be sent. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @retval false If action is set to SetValueWithoutOverwrite and the task's
* notification value cannot be updated because the target task already had a
* notification pending.
* @retval true Otherwise.
*
* <b>Example Usage</b>
* This example demonstrates how to use notifyFromISR() with the SetBits
* action. See the notify() API documentation page for examples showing how to
* use the NoAction, SetValueWithOverwrite and SetValueWithoutOverwrite
* actions.
* @include Task/notifyFromISR.cpp
*/
inline bool notifyFromISR(bool& higherPriorityTaskWoken,
const NotifyAction action,
const NotificationBits value = 0,
const UBaseType_t index = 0) const {
BaseType_t taskWoken = pdFALSE;
bool result = (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action),
&taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return result;
}
/**
* Task.hpp
*
* @brief Function that calls <tt> BaseType_t xTaskNotifyIndexedFromISR(
* TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue,
* eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyFromISR.html>
*
* @overload
*/
inline bool notifyFromISR(const NotifyAction action,
const NotificationBits value = 0,
const UBaseType_t index = 0) const {
return (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
static_cast<eNotifyAction>(action),
NULL) == pdPASS);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskNotifyWaitIndexed(
* UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t
* ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t
* xTicksToWait )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyWait.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each task has an array of 'task notifications' (or just 'notifications'),
* each of which has a state and a 32-bit value. A direct to task notification
* is an event sent directly to a task that can unblock the receiving task,
* and optionally update one of the receiving tasks notification values in a
* number of different ways. For example, a notification may overwrite one of
* the receiving tasks notification values, or just set one or more bits in
* one of the receiving tasks notification values.
*
* notifyWait() waits, with an optional timeout, for the calling task to
* receive a notification. If the receiving RTOS task was already Blocked
* waiting for a notification when the notification it is waiting for arrives
* the receiving RTOS task will be removed from the Blocked state and the
* notification cleared.
*
* @note Each notification within the array operates independently - a task
* can only block on one notification within the array at a time and will not
* be unblocked by a notification sent to any other array index.
*
* notifyGive() must not be called from an interrupt service routine. Use
* notifyGiveFromISR() instead.
*
* @param ticksToWait The maximum time to wait in the Blocked state for a
* notification to be received if a notification is not already pending when
* notifyWait() is called.
*
* The RTOS task does not consume any CPU time when it is in the Blocked
* state.
*
* The time is specified in RTOS tick periods. The pdMS_TO_TICKS() macro can
* be used to convert a time specified in milliseconds into a time specified
* in ticks.
*
* @param bitsToClearOnEntry Any bits set in bitsToClearOnEntry will be
* cleared in the calling RTOS task's notification value on entry to the
* notifyWait() function (before the task waits for a new notification)
* provided a notification is not already pending when notifyWait() is called.
*
* For example, if bitsToClearOnEntry is 0x01, then bit 0 of the task's
* notification value will be cleared on entry to the function.
*
* Setting bitsToClearOnEntry to 0xffffffff (ULONG_MAX) will clear all the
* bits in the task's notification value, effectively clearing the value to 0.
*
* @param bitsToClearOnExit Any bits set in bitsToClearOnExit will be cleared
* in the calling RTOS task's notification value before notifyWait() function
* exits if a notification was received.
*
* The bits are cleared after the RTOS task's notification value are returned.
*
* For example, if bitsToClearOnExit is 0x03, then bit 0 and bit 1 of the
* task's notification value will be cleared before the function exits.
*
* Setting bitsToClearOnExit to 0xffffffff (ULONG_MAX) will clear all the bits
* in the task's notification value, effectively clearing the value to 0.
*
* @param index The index within the calling task's array of notification
* values on which the calling task will wait for a notification to be
* received. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @retval true If a notification was received, or a notification was already
* pending when notifyWait() was called.
* @retval false If the call to notifyWait() timed out before a notification
* was received.
* @return The RTOS task's notification value as it was before any bits were
* cleared due to the bitsToClearOnExit setting.
*
* <b>Example Usage</b>
* @include Task/notifyWait.cpp
*/
inline static std::pair<bool, NotificationBits> notifyWait(
const TickType_t ticksToWait = portMAX_DELAY,
const NotificationBits bitsToClearOnEntry = 0,
const NotificationBits bitsToClearOnExit = 0,
const UBaseType_t index = 0) {
uint32_t pulNotificationValue;
bool result =
(xTaskNotifyWaitIndexed(index, bitsToClearOnEntry.to_ulong(),
bitsToClearOnExit.to_ulong(),
&pulNotificationValue, ticksToWait) == pdTRUE);
return std::make_pair(result, NotificationBits(pulNotificationValue));
}
/**
* Task.hpp
*
* @brief Function that calls <tt>BaseType_t xTaskNotifyStateClearIndexed(
* TaskHandle_t xTask, UBaseType_t uxIndexToClear )</tt>
*
* @see <https://www.freertos.org/xTaskNotifyStateClear.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each RTOS task has an array of task notifications. Each task notification
* has a notification state that can be either pending or not pending, and
* a 32-bit notification value.
*
* If a notification is sent to an index within the array of notifications
* then the notification at that index is said to be 'pending' until the task
* reads its notification value or explicitly clears the notification state to
* 'not pending' by calling notifyStateClear().
*
* @param index The index within the target task's array of notification
* values to act upon. For example, setting index to 1 will clear the state of
* the notification at index 1 within the array.
*
* index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* notifyStateClear() does not have this parameter and always acts on the
* notification at index 0.
*
* @retval true If the task had a notification pending, and the notification
* was cleared.
* @retval false If the task didn't have a notification pending.
*
* <b>Example Usage</b>
* @include Task/notifyStateClear.cpp
*/
inline bool notifyStateClear(const UBaseType_t index = 0) const {
return (xTaskNotifyStateClearIndexed(handle, index) == pdTRUE);
}
/**
* Task.hpp
*
* @brief Function that calls <tt>uint32_t ulTaskNotifyValueClearIndexed(
* TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear
* )</tt>
*
* @see <https://www.freertos.org/ulTasknotifyValueClear.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each RTOS task has an array of task notifications. Each task notification
* has a notification state that can be either pending or not pending, and
* a 32-bit notification value.
*
* notifyValueClear() clears the bits specified by the bitsToClear bit mask in
* the notification value at array index index of the task.
*
* @param bitsToClear Bit mask of the bits to clear in the notification value
* of the task. Set a bit to 1 to clear the corresponding bits in the task's
* notification value. Set bitsToClear to 0xffffffff (UINT_MAX on 32-bit
* architectures) to clear the notification value to 0. Set bitsToClear to 0
* to query the task's notification value without clearing any bits.
* @param index The index within the target task's array of notification
* values in which to clear the bits. index must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES.
* @return NotificationBits The value of the target task's notification value
* before the bits specified by bitsToClear were cleared.
*
* <b>Example Usage</b>
* @include Task/notifyValueClear.cpp
*/
inline NotificationBits notifyValueClear(
const NotificationBits bitsToClear = 0,
const UBaseType_t index = 0) const {
return NotificationBits(
ulTaskNotifyValueClearIndexed(handle, index, bitsToClear.to_ulong()));
}
#endif /* configUSE_TASK_NOTIFICATIONS */
protected:
/**
* Task.hpp
*
* @brief Abstraction function that acts as the entry point of the task for
* the user.
*/
virtual void taskFunction() = 0;
#if (INCLUDE_vTaskDelay == 1)
/**
* Task.hpp
*
* @brief Function that calls <tt>void vTaskDelay( const TickType_t
* xTicksToDelay )</tt>
*
* @see <https://www.freertos.org/a00127.html>
*
* 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.
*
* <b>Example Usage</b>
* @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 <tt>BaseType_t xTaskDelayUntil( TickType_t
* *pxPreviousWakeTime, const TickType_t xTimeIncrement )</tt>
*
* @see <https://www.freertos.org/xtaskdelayuntiltask-control.html>
*
* 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.
*
* <b>Example Usage</b>
* @include Task/delayUntil.cpp
*/
inline bool delayUntil(const TickType_t timeIncrement = 0) {
return (xTaskDelayUntil(&previousWakeTime, timeIncrement) == pdTRUE);
}
#endif /* INCLUDE_xTaskDelayUntil */
/**
* Task.hpp
*
* @brief Function that calls <tt>uint32_t ulTaskNotifyTakeIndexed(
* UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t
* xTicksToWait )</tt>
*
* @see <https://www.freertos.org/ulTaskNotifyTake.html>
*
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Each task has a private array of "notification values" (or
* 'notifications'), each of which is a 32-bit unsigned integer (uint32_t).
* The constant configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of
* indexes in the array, and (for backward compatibility) defaults to 1 if
* left undefined. Prior to FreeRTOS V10.4.0 there was only one notification
* value per task.
*
* Events can be sent to a task using an intermediary object. Examples of
* such objects are queues, semaphores, mutexes and event groups. Task
* notifications are a method of sending an event directly to a task without
* the need for such an intermediary object.
*
* A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment one of the task's notification values. In
* that way task notifications can be used to send data to a task, or be used
* as light weight and fast binary or counting semaphores.
*
* notifyTake() is intended for use when a task notification is used as a
* faster and lighter weight binary or counting semaphore alternative. Actual
* FreeRTOS semaphores are taken using the FreeRTOS::Semaphore::take() API
* function, the equivalent action that instead uses a task notification is
* notifyTake().
*
* When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification
* using the notificationTake() API function rather than the notifyWait() API
* function.
*
* notifyTake() can either clear the task's notification value at the array
* index specified by the indexToWaitOn parameter to zero on exit, in which
* case the notification value acts like a binary semaphore, or decrement the
* notification value on exit, in which case the notification value acts like
* a counting semaphore.
*
* A task can use notifyTake() to [optionally] block to wait for a
* notification. The task does not consume any CPU time while it is in the
* Blocked state.
*
* Where as notifyWait() will return when a notification is pending,
* notifyTake() will return when the task's notification value is not zero.
*
* @note Each notification within the array operates independently - a task
* can only block on one notification within the array at a time and will not
* be unblocked by a notification sent to any other array index.
*
* @param ticksToWait The maximum time to wait in the Blocked state for a
* notification to be received if a notification is not already pending when
* notifyTake() is called. The RTOS task does not consume any CPU time when
* it is in the Blocked state. The time is specified in RTOS tick periods.
* The pdMS_TO_TICKS() macro can be used to convert a time specified in
* milliseconds into a time specified in ticks.
*
* @param clearCountOnExit If an RTOS task notification is received and
* clearCountOnExit is set to false then the RTOS task's notification value is
* decremented before notifyTake() exits. This is equivalent to the value of a
* counting semaphore being decremented by a successful call to
* FreeRTOS::Semaphore::Take(). If an RTOS task notification is received and
* clearCountOnExit is set to true then the RTOS task's notification value is
* reset to 0 before notifyTake() exits. This is equivalent to the value of a
* binary semaphore being left at zero (or empty, or 'not available') after a
* successful call to FreeRTOS::Semaphore::Take().
*
* @param index The index within the calling task's array of notification
* values on which the calling task will wait for a notification to be
* non-zero. index must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
*
* @return NotificationBits The value of the task's notification value before
* it is decremented or cleared (see the description of clearCountOnExit)
*
* <b>Example Usage</b>
* @include Task/notifyTake.cpp
*/
inline static NotificationBits notifyTake(
const TickType_t ticksToWait = portMAX_DELAY,
const bool clearCountOnExit = true, const UBaseType_t index = 0) {
return NotificationBits(
ulTaskNotifyTakeIndexed(index, clearCountOnExit, ticksToWait));
}
private:
/**
* @brief Construct a new TaskBase object. This default constructor is
* deliberately private as this class is not intended to be instantiated or
* derived from by the user. Use FreeRTOS::Task or FreeRTOS::StaticTask as a
* base class for creating a task.
*/
TaskBase() = default;
TaskBase(TaskBase&&) noexcept = default;
TaskBase& operator=(TaskBase&&) noexcept = default;
/**
* Task.hpp
*
* @brief Destroy the Task object.
*
* @see <https://www.freertos.org/a00126.html>
*
* If INCLUDE_vTaskDelete is defined as 1 and the task handle is not NULL,
* then the destructor will call <tt>void vTaskDelete( TaskHandle_t xTask
* )</tt> See the RTOS Configuration documentation for more information.
*
* Calling <tt>void vTaskDelete( TaskHandle_t xTask )</tt> will remove a task
* from the RTOS kernels management. The task being deleted will be removed
* from all ready, blocked, suspended and event lists.
*
* @note The idle task is responsible for freeing the RTOS kernel allocated
* memory from tasks that have been deleted. It is therefore important that
* the idle task is not starved of microcontroller processing time if your
* application makes any calls to <tt>void vTaskDelete( TaskHandle_t xTask
* )</tt> Memory allocated by the task code is not automatically freed, and
* should be freed before the task is deleted.
*
* <b>Example Usage</b>
* @include Task/task.cpp
*/
~TaskBase() {
#if (INCLUDE_vTaskDelete == 1)
if (handle != NULL) {
vTaskDelete(handle);
}
#endif /* INCLUDE_vTaskDelete */
}
/**
* @brief Handle used to refer to the task when using the FreeRTOS interface.
*/
TaskHandle_t handle = NULL;
/**
* @brief Variable that holds the time at which the task was last unblocked.
*/
TickType_t previousWakeTime = 0;
};
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
/**
* Task Task.hpp <FreeRTOS/Task.hpp>
*
* @brief Class that encapsulates the functionality of a FreeRTOS task.
*
* Each task requires RAM that is used to hold the task state, and used by the
* task as its stack. If a task is created using this class then the required
* RAM is automatically allocated from the FreeRTOS heap. If a task is created
* using FreeRTOS::StaticTask() then the RAM is included in the object, so it
* can be statically allocated at compile time. See the Static Vs Dynamic
* allocation page for more information.
*
* @note This class is not intended to be instantiated by the user. The user
* should create a class that derives from this class and implement
* taskFunction().
*/
class Task : public TaskBase {
public:
Task(const Task&) = delete;
Task& operator=(const Task&) = delete;
/**
* @brief Function that checks the return value of the call to xTaskCreate in
* the constructor. This function should be called to ensure the task was
* created successfully before starting the scheduler.
*
* @return true If the task was created successfully.
* @return false If the task was not created successfully due to insufficient
* memory.
*/
bool isValid() const { return taskCreatedSuccessfully; }
protected:
/**
* Task.hpp
*
* @brief Construct a new Task object by calling <tt>BaseType_t xTaskCreate(
* TaskFunction_t pvTaskCode, const char * const pcName,
* configSTACK_DEPTH_TYPE usStackDepth, void *pvParameters, BaseType_t
* uxPriority, TaskHandle_t *pxCreatedTask )</tt>
*
* @see <https://www.freertos.org/a00125.html>
*
* @warning The user should call isValid() on this object to verify that the
* task was created successfully in case the memory required to create the
* task could not be allocated.
*
* @note When calling <tt>xTaskCreate</tt> the constructor passes the
* <tt>this</tt> pointer as the task function argument. This pointer is used
* so that the interface function callTaskFunction() can invoke taskEntry()
* for this instance of the class.
*
* @param priority The priority at which the created task will execute.
* Priorities are asserted to be less than configMAX_PRIORITIES. If
* configASSERT is undefined, priorities are silently capped at
* (configMAX_PRIORITIES - 1).
* @param stackDepth The number of words (not bytes!) to allocate for use as
* the task's stack. For example, if the stack is 16-bits wide and stackDepth
* is 100, then 200 bytes will be allocated for use as the task's stack. As
* another example, if the stack is 32-bits wide and stackDepth is 400 then
* 1600 bytes will be allocated for use as the task's stack. The stack depth
* multiplied by the stack width must not exceed the maximum value that can be
* contained in a variable of type size_t.
* @param name A descriptive name for the task. This is mainly used to
* facilitate debugging, but can also be used to obtain a task handle. The
* maximum length of a task's name is defined by configMAX_TASK_NAME_LEN in
* FreeRTOSConfig.h.
*
* <b>Example Usage</b>
* @include Task/task.cpp
*/
explicit Task(
const UBaseType_t priority = tskIDLE_PRIORITY,
const configSTACK_DEPTH_TYPE stackDepth = configMINIMAL_STACK_SIZE,
const char* name = "") {
taskCreatedSuccessfully = (xTaskCreate(callTaskFunction, name, stackDepth,
this, priority, &handle) == pdPASS);
}
~Task() = default;
Task(Task&&) noexcept = default;
Task& operator=(Task&&) noexcept = default;
private:
bool taskCreatedSuccessfully = false;
};
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
/**
* StaticTask Task.hpp <FreeRTOS/Task.hpp>
*
* @brief Class that encapsulates the functionality of a FreeRTOS task.
*
* Each task requires RAM that is used to hold the task state, and used by the
* task as its stack. If a task is created using this class then the RAM is
* included in the object. If a task is created using FreeRTOS::Task() then the
* required RAM is automatically allocated from the FreeRTOS heap. See the
* Static Vs Dynamic allocation page for more information.
*
* @note This class is not intended to be instantiated by the user. The user
* should create a class that derives from this class and implement
* taskFunction().
*
* @warning This class contains the task's data structures (TCB) and the array
* used to store the task's stack, so any instace of this class or class derived
* from this class must be persistent (not declared on the stack of another
* function).
*
* @tparam N The number of indexes in the array of <tt>StackType_t</tt> used to
* store the stack for this task.
*/
template <UBaseType_t N = configMINIMAL_STACK_SIZE>
class StaticTask : public TaskBase {
public:
StaticTask(const StaticTask&) = delete;
StaticTask& operator=(const StaticTask&) = delete;
protected:
/**
* Task.hpp
*
* @brief Construct a new Task object by calling <tt>TaskHandle_t
* xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName,
* const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t
* uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const
* pxTaskBuffer )</tt>
*
* @see <https://www.freertos.org/xTaskCreateStatic.html>
*
* @note When calling <tt>xTaskCreateStatic</tt> the constructor passes the
* <tt>this</tt> pointer as the task function argument. This pointer is used
* so that the interface function callTaskFunction() can invoke taskEntry()
* for this instance of the class.
*
* @param priority The priority at which the created task will execute.
* Priorities are asserted to be less than configMAX_PRIORITIES. If
* configASSERT is undefined, priorities are silently capped at
* (configMAX_PRIORITIES - 1).
* @param name A descriptive name for the task. This is mainly used to
* facilitate debugging, but can also be used to obtain a task handle. The
* maximum length of a task's name is defined by configMAX_TASK_NAME_LEN in
* FreeRTOSConfig.h.
*
* <b>Example Usage</b>
* @include Task/staticTask.cpp
*/
explicit StaticTask(const UBaseType_t priority = tskIDLE_PRIORITY,
const char* name = "") {
handle = xTaskCreateStatic(callTaskFunction, name, N, this, priority, stack,
&taskBuffer);
}
~StaticTask() = default;
StaticTask(StaticTask&&) noexcept = default;
StaticTask& operator=(StaticTask&&) noexcept = default;
private:
StaticTask_t taskBuffer;
StackType_t stack[N];
};
#endif /* configSUPPORT_STATIC_ALLOCATION */
} // namespace FreeRTOS
inline void callTaskFunction(void* task) {
static_cast<FreeRTOS::TaskBase*>(task)->taskEntry();
}
#endif // FREERTOS_TASK_HPP