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

1484 lines
62 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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