FreeRTOS-Cpp
Task.hpp
1 /*
2  * FreeRTOS-Cpp
3  * Copyright (C) 2021 Jon Enz. All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * https://github.com/jonenz/FreeRTOS-Cpp
26  */
27 
28 #ifndef FREERTOS_TASK_HPP
29 #define FREERTOS_TASK_HPP
30 
31 #include <FreeRTOS/Kernel.hpp>
32 #include <bitset>
33 #include <utility>
34 
35 #include "FreeRTOS.h"
36 #include "task.h"
37 
46 void callTaskFunction(void* task);
47 
48 namespace FreeRTOS {
49 
60 class TaskBase {
61  public:
62  friend class Task;
63  template <UBaseType_t>
64  friend class StaticTask;
65 
66  TaskBase(const TaskBase&) = delete;
67  TaskBase& operator=(const TaskBase&) = delete;
68 
69  static void* operator new(size_t, void* ptr) { return ptr; }
70  static void* operator new[](size_t, void* ptr) { return ptr; }
71  static void* operator new(size_t) = delete;
72  static void* operator new[](size_t) = delete;
73 
74  enum class State {
75  Running = eRunning,
76  Ready = eReady,
77  Blocked = eBlocked,
78  Suspended = eSuspended,
79  Deleted = eDeleted,
80  Invalid = eInvalid,
81  };
82 
83  enum class NotifyAction {
84  NoAction = eNoAction,
85  SetBits = eSetBits,
86  Increment = eIncrement,
87  SetValueWithOverwrite = eSetValueWithOverwrite,
88  SetValueWithoutOverwrite = eSetValueWithoutOverwrite,
89  };
90 
91  // NOLINTNEXTLINE
92  using NotificationBits = std::bitset<32>;
93 
105  virtual inline void taskEntry() final {
107  taskFunction();
108  };
109 
110 #if (INCLUDE_uxTaskPriorityGet == 1)
129  inline UBaseType_t getPriority() const { return uxTaskPriorityGet(handle); }
130 #endif /* INCLUDE_uxTaskPriorityGet */
131 
132 #if (INCLUDE_vTaskPrioritySet == 1)
154  inline void setPriority(const UBaseType_t newPriority) const {
155  vTaskPrioritySet(handle, newPriority);
156  }
157 #endif /* INCLUDE_vTaskPrioritySet */
158 
159 #if (INCLUDE_vTaskSuspend == 1)
181  inline void suspend() const { vTaskSuspend(handle); }
182 
202  inline void resume() const { vTaskResume(handle); }
203 
204 #if (INCLUDE_xTaskResumeFromISR == 1)
234  inline bool resumeFromISR() const {
235  return (xTaskResumeFromISR(handle) == pdTRUE);
236  }
237 #endif /* INCLUDE_xTaskResumeFromISR */
238 #endif /* INCLUDE_vTaskSuspend */
239 
240 #if (INCLUDE_xTaskAbortDelay == 1)
268  inline bool abortDelay() const { return (xTaskAbortDelay(handle) == pdPASS); }
269 #endif /* INCLUDE_xTaskAbortDelay */
270 
271 #if (INCLUDE_xTaskGetIdleTaskHandle == 1)
289  inline static TaskHandle_t getIdleHandle() {
290  return xTaskGetIdleTaskHandle();
291  }
292 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
293 
294 #if (INCLUDE_uxTaskGetStackHighWaterMark == 1)
321  inline UBaseType_t getStackHighWaterMark() const {
322  return uxTaskGetStackHighWaterMark(handle);
323  }
324 
348  inline configSTACK_DEPTH_TYPE getStackHighWaterMark2() const {
349  return uxTaskGetStackHighWaterMark2(handle);
350  }
351 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
352 
353 #if (INCLUDE_eTaskGetState == 1)
374  inline State getState() const {
375  return static_cast<State>(eTaskGetState(handle));
376  }
377 #endif /* INCLUDE_eTaskGetState */
378 
392  inline const char* getName() const { return pcTaskGetName(handle); }
393 
394 #if (INCLUDE_xTaskGetHandle == 1)
413  inline static TaskHandle_t getHandle(const char* name) {
414  return xTaskGetHandle(name);
415  }
416 #endif /* INCLUDE_xTaskGetHandle */
417 
418 #if (configUSE_TASK_NOTIFICATIONS == 1)
468  inline void notifyGive(const UBaseType_t index = 0) const {
469  xTaskNotifyGiveIndexed(handle, index);
470  }
471 
497  inline void notifyGiveFromISR(bool& higherPriorityTaskWoken,
498  const UBaseType_t index = 0) const {
499  BaseType_t taskWoken = pdFALSE;
500  vTaskNotifyGiveIndexedFromISR(handle, index, &taskWoken);
501  if (taskWoken == pdTRUE) {
502  higherPriorityTaskWoken = true;
503  }
504  }
505 
517  inline void notifyGiveFromISR(const UBaseType_t index = 0) const {
518  vTaskNotifyGiveIndexedFromISR(handle, index, NULL);
519  }
520 
603  inline bool notify(const NotifyAction action,
604  const NotificationBits value = 0,
605  const UBaseType_t index = 0) const {
606  return (xTaskNotifyIndexed(handle, index, value.to_ulong(),
607  static_cast<eNotifyAction>(action)) == pdPASS);
608  }
609 
663  inline std::pair<bool, NotificationBits> notifyAndQuery(
664  const NotifyAction action, const NotificationBits value = 0,
665  const UBaseType_t index = 0) const {
666  uint32_t pulNotificationValue;
667  bool result =
668  (xTaskNotifyAndQueryIndexed(handle, index, value.to_ulong(),
669  static_cast<eNotifyAction>(action),
670  &pulNotificationValue) == pdPASS);
671 
672  return std::make_pair(result, NotificationBits(pulNotificationValue));
673  }
674 
748  inline std::pair<bool, NotificationBits> notifyAndQueryFromISR(
749  bool& higherPriorityTaskWoken, const NotifyAction action,
750  const NotificationBits value = 0, const UBaseType_t index = 0) const {
751  BaseType_t taskWoken = pdFALSE;
752  uint32_t pulNotificationValue;
753  bool result = (xTaskNotifyAndQueryIndexedFromISR(
754  handle, index, value.to_ulong(),
755  static_cast<eNotifyAction>(action),
756  &pulNotificationValue, &taskWoken) == pdPASS);
757 
758  if (taskWoken == pdTRUE) {
759  higherPriorityTaskWoken = true;
760  }
761 
762  return std::make_pair(result, NotificationBits(pulNotificationValue));
763  }
764 
778  inline std::pair<bool, NotificationBits> notifyAndQueryFromISR(
779  const NotifyAction action, const NotificationBits value = 0,
780  const UBaseType_t index = 0) const {
781  uint32_t pulNotificationValue;
782  bool result = (xTaskNotifyAndQueryIndexedFromISR(
783  handle, index, value.to_ulong(),
784  static_cast<eNotifyAction>(action),
785  &pulNotificationValue, NULL) == pdPASS);
786 
787  return std::make_pair(result, NotificationBits(pulNotificationValue));
788  }
789 
852  inline bool notifyFromISR(bool& higherPriorityTaskWoken,
853  const NotifyAction action,
854  const NotificationBits value = 0,
855  const UBaseType_t index = 0) const {
856  BaseType_t taskWoken = pdFALSE;
857  bool result = (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
858  static_cast<eNotifyAction>(action),
859  &taskWoken) == pdPASS);
860  if (taskWoken == pdTRUE) {
861  higherPriorityTaskWoken = true;
862  }
863  return result;
864  }
865 
877  inline bool notifyFromISR(const NotifyAction action,
878  const NotificationBits value = 0,
879  const UBaseType_t index = 0) const {
880  return (xTaskNotifyIndexedFromISR(handle, index, value.to_ulong(),
881  static_cast<eNotifyAction>(action),
882  NULL) == pdPASS);
883  }
884 
967  inline static std::pair<bool, NotificationBits> notifyWait(
968  const TickType_t ticksToWait = portMAX_DELAY,
969  const NotificationBits bitsToClearOnEntry = 0,
970  const NotificationBits bitsToClearOnExit = 0,
971  const UBaseType_t index = 0) {
972  uint32_t pulNotificationValue;
973  bool result =
974  (xTaskNotifyWaitIndexed(index, bitsToClearOnEntry.to_ulong(),
975  bitsToClearOnExit.to_ulong(),
976  &pulNotificationValue, ticksToWait) == pdTRUE);
977  return std::make_pair(result, NotificationBits(pulNotificationValue));
978  }
979 
1016  inline bool notifyStateClear(const UBaseType_t index = 0) const {
1017  return (xTaskNotifyStateClearIndexed(handle, index) == pdTRUE);
1018  }
1019 
1053  inline NotificationBits notifyValueClear(
1054  const NotificationBits bitsToClear = 0,
1055  const UBaseType_t index = 0) const {
1056  return NotificationBits(
1057  ulTaskNotifyValueClearIndexed(handle, index, bitsToClear.to_ulong()));
1058  }
1059 #endif /* configUSE_TASK_NOTIFICATIONS */
1060 
1061  protected:
1068  virtual void taskFunction() = 0;
1069 
1070 #if (INCLUDE_vTaskDelay == 1)
1105  inline static void delay(const TickType_t ticksToDelay = 0) {
1106  vTaskDelay(ticksToDelay);
1107  }
1108 #endif /* INCLUDE_vTaskDelay */
1109 
1110 #if (INCLUDE_xTaskDelayUntil == 1)
1151  inline bool delayUntil(const TickType_t timeIncrement = 0) {
1152  return (xTaskDelayUntil(&previousWakeTime, timeIncrement) == pdTRUE);
1153  }
1154 #endif /* INCLUDE_xTaskDelayUntil */
1155 
1240  inline static NotificationBits notifyTake(
1241  const TickType_t ticksToWait = portMAX_DELAY,
1242  const bool clearCountOnExit = true, const UBaseType_t index = 0) {
1243  return NotificationBits(
1244  ulTaskNotifyTakeIndexed(index, clearCountOnExit, ticksToWait));
1245  }
1246 
1247  private:
1254  TaskBase() = default;
1255 
1256  TaskBase(TaskBase&&) noexcept = default;
1257  TaskBase& operator=(TaskBase&&) noexcept = default;
1258 
1285 #if (INCLUDE_vTaskDelete == 1)
1286 
1287  if (handle != NULL) {
1288  vTaskDelete(handle);
1289  }
1290 
1291 #endif /* INCLUDE_vTaskDelete */
1292  }
1293 
1297  TaskHandle_t handle = NULL;
1298 
1302  TickType_t previousWakeTime = 0;
1303 };
1304 
1305 #if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
1306 
1323 class Task : public TaskBase {
1324  public:
1325  Task(const Task&) = delete;
1326  Task& operator=(const Task&) = delete;
1327 
1337  bool isValid() const { return taskCreatedSuccessfully; }
1338 
1339  protected:
1378  explicit Task(
1379  const UBaseType_t priority = tskIDLE_PRIORITY,
1380  const configSTACK_DEPTH_TYPE stackDepth = configMINIMAL_STACK_SIZE,
1381  const char* name = "") {
1382  taskCreatedSuccessfully = (xTaskCreate(callTaskFunction, name, stackDepth,
1383  this, priority, &handle) == pdPASS);
1384  }
1385 
1386  ~Task() = default;
1387 
1388  Task(Task&&) noexcept = default;
1389  Task& operator=(Task&&) noexcept = default;
1390 
1391  private:
1392  bool taskCreatedSuccessfully = false;
1393 };
1394 
1395 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
1396 
1397 #if (configSUPPORT_STATIC_ALLOCATION == 1)
1398 
1422 template <UBaseType_t N = configMINIMAL_STACK_SIZE>
1423 class StaticTask : public TaskBase {
1424  public:
1425  StaticTask(const StaticTask&) = delete;
1426  StaticTask& operator=(const StaticTask&) = delete;
1427 
1428  protected:
1457  explicit StaticTask(const UBaseType_t priority = tskIDLE_PRIORITY,
1458  const char* name = "") {
1459  handle = xTaskCreateStatic(callTaskFunction, name, N, this, priority, stack,
1460  &taskBuffer);
1461  }
1462  ~StaticTask() = default;
1463 
1464  StaticTask(StaticTask&&) noexcept = default;
1465  StaticTask& operator=(StaticTask&&) noexcept = default;
1466 
1467  private:
1468  StaticTask_t taskBuffer;
1469  StackType_t stack[N];
1470 };
1471 
1472 #endif /* configSUPPORT_STATIC_ALLOCATION */
1473 
1474 } // namespace FreeRTOS
1475 
1476 inline void callTaskFunction(void* task) {
1477  static_cast<FreeRTOS::TaskBase*>(task)->taskEntry();
1478 }
1479 
1480 #endif // FREERTOS_TASK_HPP
Class that encapsulates the functionality of a FreeRTOS task.
Definition: Task.hpp:1423
StaticTask(const UBaseType_t priority=tskIDLE_PRIORITY, const char *name="")
Construct a new Task object by calling TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,...
Definition: Task.hpp:1457
Base class that provides the standard task interface to FreeRTOS::Task and FreeRTOS::StaticTask.
Definition: Task.hpp:60
bool notifyFromISR(const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:877
bool notifyStateClear(const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexT...
Definition: Task.hpp:1016
static TaskHandle_t getIdleHandle()
Function that calls TaskHandle_t xTaskGetIdleTaskHandle( void )
Definition: Task.hpp:289
UBaseType_t getPriority() const
Function that calls UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
Definition: Task.hpp:129
void notifyGiveFromISR(const UBaseType_t index=0) const
Function that calls void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndex...
Definition: Task.hpp:517
bool notify(const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToN...
Definition: Task.hpp:603
virtual void taskFunction()=0
Abstraction function that acts as the entry point of the task for the user.
static void delay(const TickType_t ticksToDelay=0)
Function that calls void vTaskDelay( const TickType_t xTicksToDelay )
Definition: Task.hpp:1105
void setPriority(const UBaseType_t newPriority) const
Function that calls void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
Definition: Task.hpp:154
std::pair< bool, NotificationBits > notifyAndQueryFromISR(const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:778
virtual void taskEntry() final
Function that acts as the entry point of the task instance. This function initializes the previous wa...
Definition: Task.hpp:105
bool notifyFromISR(bool &higherPriorityTaskWoken, const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:852
State getState() const
Function that calls UBaseType_t uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
Definition: Task.hpp:374
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)
Function that calls BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn,...
Definition: Task.hpp:967
std::pair< bool, NotificationBits > notifyAndQuery(const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:663
const char * getName() const
Function that calls char *pcTaskGetName( TaskHandle_t xTaskToQuery )
Definition: Task.hpp:392
bool resumeFromISR() const
Function that calls BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
Definition: Task.hpp:234
NotificationBits notifyValueClear(const NotificationBits bitsToClear=0, const UBaseType_t index=0) const
Function that calls uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexTo...
Definition: Task.hpp:1053
UBaseType_t getStackHighWaterMark() const
Function that calls UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
Definition: Task.hpp:321
bool abortDelay() const
Function that calls BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
Definition: Task.hpp:268
TaskBase()=default
Construct a new TaskBase object. This default constructor is deliberately private as this class is no...
TaskHandle_t handle
Handle used to refer to the task when using the FreeRTOS interface.
Definition: Task.hpp:1297
configSTACK_DEPTH_TYPE getStackHighWaterMark2() const
Function that calls UBaseType_t uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
Definition: Task.hpp:348
static TaskHandle_t getHandle(const char *name)
Function that calls TaskHandle_t xTaskGetHandle( const char *pcNameToQuery )
Definition: Task.hpp:413
static NotificationBits notifyTake(const TickType_t ticksToWait=portMAX_DELAY, const bool clearCountOnExit=true, const UBaseType_t index=0)
Function that calls uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn,...
Definition: Task.hpp:1240
void notifyGive(const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:468
std::pair< bool, NotificationBits > notifyAndQueryFromISR(bool &higherPriorityTaskWoken, const NotifyAction action, const NotificationBits value=0, const UBaseType_t index=0) const
Function that calls BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify,...
Definition: Task.hpp:748
TickType_t previousWakeTime
Variable that holds the time at which the task was last unblocked.
Definition: Task.hpp:1302
void notifyGiveFromISR(bool &higherPriorityTaskWoken, const UBaseType_t index=0) const
Function that calls void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndex...
Definition: Task.hpp:497
void resume() const
Function that calls void vTaskResume( TaskHandle_t xTaskToResume )
Definition: Task.hpp:202
bool delayUntil(const TickType_t timeIncrement=0)
Function that calls BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTim...
Definition: Task.hpp:1151
void suspend() const
Function that calls void vTaskSuspend( TaskHandle_t xTaskToSuspend )
Definition: Task.hpp:181
Class that encapsulates the functionality of a FreeRTOS task.
Definition: Task.hpp:1323
bool isValid() const
Function that checks the return value of the call to xTaskCreate in the constructor....
Definition: Task.hpp:1337
Task(const UBaseType_t priority=tskIDLE_PRIORITY, const configSTACK_DEPTH_TYPE stackDepth=configMINIMAL_STACK_SIZE, const char *name="")
Construct a new Task object by calling BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,...
Definition: Task.hpp:1378
TickType_t getTickCount()
Function that calls xTaskGetTickCount()
Definition: Kernel.hpp:122