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

929 lines
38 KiB
C++
Raw Permalink 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_TIMER_HPP
#define FREERTOS_TIMER_HPP
#include "FreeRTOS.h"
#include "timers.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::TimerBase.
*/
void callTimerFunction(TimerHandle_t timer);
namespace FreeRTOS {
/**
* @class TimerBase Timer.hpp <FreeRTOS/Timer.hpp>
*
* @brief Base class that provides the standard task interface to
* FreeRTOS::Timer and FreeRTOS::StaticTimer.
*
* @note This class is not intended to be instantiated or derived from by the
* user. Use FreeRTOS::Timer or FreeRTOS::StaticTimer as a base class for a user
* implemented task.
*/
class TimerBase {
public:
friend class Timer;
friend class StaticTimer;
TimerBase(const TimerBase&) = delete;
TimerBase& operator=(const TimerBase&) = 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;
/**
* Timer.hpp
*
* @brief Function that acts as the entry point of the timer instance.
*
* @note This function is only public so that it can be accessed by the C
* interface function <tt>callTimerFunction()</tt> and should not be called or
* referenced by the user.
*/
virtual inline void timerEntry() final { timerFunction(); }
/**
* Timer.hpp
*
* @brief Function that checks the value of the timer handle. This function
* should be called to ensure the timer was created successfully.
*
* @return true If the timer was created successfully.
* @return false If the timer was not created successfully due to insufficient
* memory.
*/
inline bool isValid() const { return (handle != NULL); }
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerIsTimerActive(
* TimerHandle_t xTimer )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerIsTimerActive.html>
*
* Queries a software timer to see if it is active or dormant.
*
* A timer will be dormant if:
* -# It has been created but not started, or
* -# It is an expired one-shot timer that has not been restarted.
*
* @note Timers are created in the dormant state. The start(), reset(),
* startFromISR(), resetFromISR(), changePeriod() and changePeriodFromISR()
* API functions can all be used to transition a timer into the active state.
*
* @return false If the timer is dormant.
* @return true Otherwise.
*
* <b>Example Usage</b>
* @include Timer/isActive.cpp
*/
inline bool isActive() const {
return (xTimerIsTimerActive(handle) != pdFALSE);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStart( TimerHandle_t
* xTimer, TickType_t xBlockTime )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStart.html>
*
* start() starts a timer. If the timer had already been started and was
* already in the active state, then start() has equivalent functionality to
* the reset() API function.
*
* Starting a timer ensures the timer is in the active state. If the timer is
* not stopped, deleted, or reset in the mean time, timerFunction() will get
* called 'n 'ticks after start() was called, where 'n' is the timers defined
* period.
*
* It is valid to call start() before the RTOS scheduler has been started, but
* when this is done the timer will not actually start until the RTOS
* scheduler is started, and the timers expiry time will be relative to when
* the RTOS scheduler is started, not relative to when start() was called.
*
* @param blockTime Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the start command to be
* successfully sent to the timer command queue, should the queue already be
* full when start() was called. blockTime is ignored if start() is called
* before the RTOS scheduler is started.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system,
* although the timers expiry time is relative to when start() is actually
* called. The timer service/daemon task priority is set by the
* configTIMER_TASK_PRIORITY configuration constant.
* @return false If the start command could not be sent to the timer command
* queue even after blockTime ticks had passed.
*
* <b>Example Usage</b>
* @include Timer/timer.cpp
*/
inline bool start(const TickType_t blockTime = 0) const {
return (xTimerStart(handle, blockTime) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStartFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStartFromISR.html>
*
* A version of start() that can be called from an interrupt service routine.
*
* @param higherPriorityTaskWoken The timer service/daemon task spends most of
* its time in the Blocked state, waiting for messages to arrive on the timer
* command queue. Calling startFromISR() writes a message to the timer command
* queue, so has the potential to transition the timer service/daemon task out
* of the Blocked state. If calling startFromISR() causes the timer
* service/daemon task to leave the Blocked state, and the timer service/
* daemon task has a priority equal to or greater than the currently executing
* task (the task that was interrupted), then higherPriorityTaskWoken will get
* set to true internally within the startFromISR() function. If
* startFromISR() sets this value to true, then a context switch should be
* performed before the interrupt exits.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system,
* although the timers expiry time is relative to when startFromISR() is
* actually called. The timer service/daemon task priority is set by the
* configTIMER_TASK_PRIORITY configuration constant.
* @return false If the start command could not be sent to the timer command
* queue.
*
* <b>Example Usage</b>
* @include Timer/startFromISR.cpp
*/
inline bool startFromISR(bool& higherPriorityTaskWoken) const {
BaseType_t taskWoken = pdFALSE;
bool result = (xTimerStartFromISR(handle, &taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return result;
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStartFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStartFromISR.html>
*
* @overload
*/
inline bool startFromISR() const {
return (xTimerStartFromISR(handle, NULL) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStop( TimerHandle_t xTimer,
* TickType_t xBlockTime )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStop.html>
*
* stop() stops a timer that was previously started using either of the
* start(), reset(), startFromISR(), resetFromISR(), changePeriod() and
* changePeriodFromISR() API functions.
*
* Stopping a timer ensures the timer is not in the active state.
*
* @param blockTime Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the stop command to be
* successfully sent to the timer command queue, should the queue already be
* full when stop() was called. blockTime is ignored if stop() is called
* before the RTOS scheduler is started.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* @return false If the stop command could not be sent to the timer command
* queue even after blockTime ticks had passed.
*
* <b>Example Usage</b>
* @include Timer/timer.cpp
*/
inline bool stop(const TickType_t blockTime = 0) const {
return (xTimerStop(handle, blockTime) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStopFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStopFromISR.html>
*
* A version of stop() that can be called from an interrupt service routine.
*
* @param higherPriorityTaskWoken The timer service/daemon task spends most of
* its time in the Blocked state, waiting for messages to arrive on the timer
* command queue. Calling stopFromISR() writes a message to the timer command
* queue, so has the potential to transition the timer service/daemon task out
* of the Blocked state. If calling stopFromISR() causes the timer
* service/daemon task to leave the Blocked state, and the timer service/
* daemon task has a priority equal to or greater than the currently executing
* task (the task that was interrupted), then higherPriorityTaskWoken will get
* set to true internally within the stopFromISR() function. If stopFromISR()
* sets this value to true, then a context switch should be performed before
* the interrupt exits.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* @return false If the start command could not be sent to the timer command
* queue.
*
* <b>Example Usage</b>
* @include Timer/stopFromISR.cpp
*/
inline bool stopFromISR(bool& higherPriorityTaskWoken) const {
BaseType_t taskWoken = pdFALSE;
bool result = (xTimerStopFromISR(handle, &taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return result;
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerStopFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerStopFromISR.html>
*
* @overload
*/
inline bool stopFromISR() const {
return (xTimerStopFromISR(handle, NULL) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerChangePeriod( TimerHandle_t
* xTimer, TickType_t xNewPeriod, TickType_t xBlockTime )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerChangePeriod.html>
*
* changePeriod() changes the period of a timer.
*
* changePeriod() can be called to change the period of an active or dormant
* state timer. Changing the period of a dormant timers will also start the
* timer.
*
* @param newPeriod The new period for timer. Timer periods are specified in
* tick periods, so the constant portTICK_PERIOD_MS can be used to convert a
* time that has been specified in milliseconds. For example, if the timer
* must expire after 100 ticks, then newPeriod should be set to 100.
* Alternatively, if the timer must expire after 500ms, then newPeriod can be
* set to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less
* than or equal to 1000.
* @param blockTime Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the change period command to be
* successfully sent to the timer command queue, should the queue already be
* full when changePeriod() was called. blockTime is ignored if changePeriod()
* is called before the RTOS scheduler is started.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* @return false If the change period command could not be sent to the timer
* command queue even after blockTime ticks had passed.
*
* <b>Example Usage</b>
* @include Timer/changePeriod.cpp
*/
inline bool changePeriod(const TickType_t newPeriod,
const TickType_t blockTime = 0) const {
return (xTimerChangePeriod(handle, newPeriod, blockTime) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerChangePeriodFromISR(
* TimerHandle_t xTimer, TickType_t xNewPeriod, BaseType_t
* *pxHigherPriorityTaskWoken )</tt>
*
* @see
* <https://www.freertos.org/FreeRTOS-timers-xTimerChangePeriodFromISR.html>
*
* A version of changePeriod() that can be called from an interrupt service
* routine.
*
* @param newPeriod The new period for timer. Timer periods are specified in
* tick periods, so the constant portTICK_PERIOD_MS can be used to convert a
* time that has been specified in milliseconds. For example, if the timer
* must expire after 100 ticks, then newPeriod should be set to 100.
* Alternatively, if the timer must expire after 500ms, then newPeriod can be
* set to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less
* than or equal to 1000.
* @param higherPriorityTaskWoken The timer service/daemon task spends most of
* its time in the Blocked state, waiting for messages to arrive on the timer
* command queue. Calling changePeriodFromISR() writes a message to the timer
* command queue, so has the potential to transition the timer service/ daemon
* task out of the Blocked state. If calling changePeriodFromISR() causes the
* timer service/daemon task to leave the Blocked state, and the timer
* service/daemon task has a priority equal to or greater than the currently
* executing task (the task that was interrupted), then
* higherPriorityTaskWoken will get set to true internally within the
* changePeriodFromISR() function. If changePeriodFromISR() sets this value to
* true, then a context switch should be performed before the interrupt exits.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* @return false If the change period command could not be sent to the timer
* command queue.
*
* <b>Example Usage</b>
* @include Timer/changePeriodFromISR.cpp
*/
inline bool changePeriodFromISR(bool& higherPriorityTaskWoken,
const TickType_t newPeriod) const {
BaseType_t taskWoken = pdFALSE;
bool result =
(xTimerChangePeriodFromISR(handle, newPeriod, &taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return result;
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerChangePeriodFromISR(
* TimerHandle_t xTimer, TickType_t xNewPeriod, BaseType_t
* *pxHigherPriorityTaskWoken )</tt>
*
* @see
* <https://www.freertos.org/FreeRTOS-timers-xTimerChangePeriodFromISR.html>
*
* @overload
*/
inline bool changePeriodFromISR(const TickType_t newPeriod) const {
return (xTimerChangePeriodFromISR(handle, newPeriod, NULL) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerDelete( TimerHandle_t
* xTimer, TickType_t xBlockTime )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerDelete.html>
*
* deleteTimer() deletes a timer from the FreeRTOS timer task.
*
* @note This function is also called in the destructor of the timer using the
* deleteBlockTime specified when the object was created. This function
* should be used when the user wants to delete the timer from the FreeRTOS
* timer task without destroying the timer object or with a different block
* time than what was specified in the constructor.
*
* @param blockTime Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the delete command to be
* successfully sent to the timer command queue, should the queue already be
* full when deleteTimer() was called. blockTime is ignored if deleteTimer()
* is called before the RTOS scheduler is started.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system. The
* timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY
* configuration constant.
* @return false If the delete command could not be sent to the timer command
* queue even after blockTime ticks had passed.
*
* <b>Example Usage</b>
* @include Timer/changePeriod.cpp
*/
inline bool deleteTimer(const TickType_t blockTime = 0) {
if (xTimerDelete(handle, blockTime) == pdPASS) {
handle = NULL;
return true;
}
return false;
}
/**
* Timer.hpp
*
* @brief Function that calls <tt> BaseType_t xTimerReset( TimerHandle_t
* xTimer, TickType_t xBlockTime )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerReset.html>
*
* reset() re-starts a timer. If the timer had already been started and was
* already in the active state, then reset() will cause the timer to
* re-evaluate its expiry time so that it is relative to when reset() was
* called. If the timer was in the dormant state then reset() has equivalent
* functionality to the start() API function.
*
* Resetting a timer ensures the timer is in the active state. If the timer
* is not stopped, deleted, or reset in the mean time, the callback function
* associated with the timer will get called 'n' ticks after reset() was
* called, where 'n' is the timers defined period.
*
* It is valid to call reset() before the RTOS scheduler has been started, but
* when this is done the timer will not actually start until the RTOS
* scheduler is started, and the timers expiry time will be relative to when
* the RTOS scheduler is started, not relative to when reset() was called.
*
* @param blockTime Specifies the time, in ticks, that the calling task should
* be held in the Blocked state to wait for the reset command to be
* successfully sent to the timer command queue, should the queue already be
* full when reset() was called. blockTime is ignored if reset() is called
* before the RTOS scheduler is started.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system,
* although the timers expiry time is relative to when reset() is actually
* called. The timer service/daemon task priority is set by the
* configTIMER_TASK_PRIORITY configuration constant.
* @return false If the reset command could not be sent to the timer command
* queue even after blockTime ticks had passed.
*
* <b>Example Usage</b>
* @include Timer/reset.cpp
*/
inline bool reset(const TickType_t blockTime = 0) const {
return (xTimerReset(handle, blockTime) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerResetFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerResetFromISR.html>
*
* A version of reset() that can be called from an interrupt service routine.
*
* @param higherPriorityTaskWoken The timer service/daemon task spends most of
* its time in the Blocked state, waiting for messages to arrive on the timer
* command queue. Calling resetFromISR() writes a message to the timer command
* queue, so has the potential to transition the timer service/daemon task out
* of the Blocked state. If calling resetFromISR() causes the timer
* service/daemon task to leave the Blocked state, and the timer
* service/daemon task has a priority equal to or greater than the currently
* executing task (the task that was interrupted), then
* higherPriorityTaskWoken will get set to true internally within the
* resetFromISR() function. If resetFromISR() sets this value to true, then a
* context switch should be performed before the interrupt exits.
* @return true If the command was successfully sent to the timer command
* queue. When the command is actually processed will depend on the priority
* of the timer service/daemon task relative to other tasks in the system,
* although the timers expiry time is relative to when resetFromISR() is
* actually called. The timer service/daemon task priority is set by the
* configTIMER_TASK_PRIORITY configuration constant.
* @return false If the change period command could not be sent to the timer
* command queue.
*
* <b>Example Usage</b>
* @include Timer/resetFromISR.cpp
*/
inline bool resetFromISR(bool& higherPriorityTaskWoken) const {
BaseType_t taskWoken = pdFALSE;
bool result = (xTimerResetFromISR(handle, &taskWoken) == pdPASS);
if (taskWoken == pdTRUE) {
higherPriorityTaskWoken = true;
}
return result;
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>BaseType_t xTimerResetFromISR( TimerHandle_t
* xTimer, BaseType_t *pxHigherPriorityTaskWoken )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerResetFromISR.html>
*
* @overload
*/
inline bool resetFromISR() const {
return (xTimerResetFromISR(handle, NULL) == pdPASS);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>void vTimerSetReloadMode( TimerHandle_t
* xTimer, const UBaseType_t uxAutoReload )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-Timers-vTimerSetReloadMode.html>
*
* Updates the 'mode' of a software timer to be either an auto reload timer or
* a one-shot timer.
*
* An auto reload timer resets itself each time it expires, causing the timer
* to expire (and therefore execute its callback) periodically.
*
* A one shot timer does not automatically reset itself, so will only expire
* (and therefore execute its callback) once unless it is manually restarted.
*
* @param autoReload Set autoReload to true to set the timer into auto reload
* mode, or false to set the timer into one shot mode.
*/
inline void setReloadMode(const bool autoReload) const {
vTimerSetReloadMode(handle, (autoReload ? pdTRUE : pdFALSE));
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>const char * pcTimerGetName( TimerHandle_t
* xTimer )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-pcTimerGetName.html>
*
* Returns the human readable text name of a software timer.
*
* Text names are assigned to timers in the constructor.
*
* @return const char* A pointer to the text name of the timer as a standard
* NULL terminated C string.
*
* <b>Example Usage</b>
* @include Timer/getName.cpp
*/
inline const char* getName() const { return pcTimerGetName(handle); }
/**
* Timer.hpp
*
* @brief Function that calls <tt>TickType_t xTimerGetPeriod( TimerHandle_t
* xTimer )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerGetPeriod.html>
*
* Returns the period of a software timer. The period is specified in ticks.
*
* The period of a timer is initially set using the period parameter of the
* constructor. It can then be changed using the changePeriod() and
* changePeriodFromISR() API functions.
*
* @return TickType_t The period of the timer, in ticks.
*
* <b>Example Usage</b>
* @include Timer/getPeriod.cpp
*/
inline TickType_t getPeriod() const { return xTimerGetPeriod(handle); }
/**
* Timer.hpp
*
* @brief Function that calls <tt>TickType_t xTimerGetExpiryTime(
* TimerHandle_t xTimer )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerGetExpiryTime.html>
*
* Returns the time at which the software timer will expire, which is the time
* at which the timer's callback function will execute.
*
* If the value returned by getExpiryTime() is less than the current time then
* the timer will expire after the tick count has overflowed and wrapped back
* to 0. Overflows are handled in the RTOS implementation itself, so a timer's
* callback function will execute at the correct time whether it is before or
* after the tick count overflows.
*
* @return TickType_t If the timer is active, then the time at which the timer
* will next expire is returned (which may be after the current tick count has
* overflowed, see the notes above). If the timer is not active then the
* return value is undefined.
*
* <b>Example Usage</b>
* @include Timer/getExpiryTime.cpp
*/
inline TickType_t getExpiryTime() const {
return xTimerGetExpiryTime(handle);
}
/**
* Timer.hpp
*
* @brief Function that calls <tt>UBaseType_t uxTimerGetReloadMode(
* TimerHandle_t xTimer )</tt>
*
* @see <https://www.freertos.org/uxTimerGetReloadMode.html>
*
* Queries the 'mode' of the software timer.
*
* The mode can be either an auto-reloaded timer, which automatically resets
* itself each time it expires, or a one-shot timer, which will expire only
* once unless it is manually restarted.
*
* @return true If the timer is an auto-reload timer.
* @return false Otherwise.
*/
inline bool getReloadMode() const {
return (uxTimerGetReloadMode(handle) == pdTRUE);
}
/**
* Timer.hpp
*
* @brief Set the delete block time. This value is used when the destructor
* calls deleteTimer().
*
* @param deleteBlockTime Delete block time to be set in ticks.
*/
inline void setDeleteBlockTime(const TickType_t deleteBlockTime = 0) {
this->deleteBlockTime = deleteBlockTime;
}
/**
* Timer.hpp
*
* @brief Set the delete block time. This value is used when the destructor
* calls deleteTimer().
*
* @return TickType_t Delete block time in ticks.
*/
inline TickType_t getDeleteBlockTime() const { return deleteBlockTime; }
protected:
/**
* Timer.hpp
*
* @brief Abstraction function that acts as the entry point of the timer
* callback for the user.
*/
virtual void timerFunction() = 0;
private:
/**
* Timer.hpp
*
* @brief Construct a new TimerBase object. This default constructor is
* deliberately private as this class is not intended to be instantiated or
* derived from by the user. Use FreeRTOS::Timer or FreeRTOS::StaticTimer as
* a base class for creating a task.
*
* @param deleteBlockTime Set the delete block time. This value is used when
* the destructor calls deleteTimer().
*/
explicit TimerBase(const TickType_t deleteBlockTime = 0)
: deleteBlockTime(deleteBlockTime) {}
/**
* Timer.hpp
*
* @brief Destroy the TimerBase object.
*
* @note This destructor will check that the timer is still valid and has not
* already been deleted by deleteTimer() before calling the function. If the
* timer is still valid the destructor will call deleteTimer() and block for
* up to the amount of time specified by deleteBlockTime.
*/
~TimerBase() {
if (isValid()) {
deleteTimer(getDeleteBlockTime());
}
}
TimerBase(TimerBase&&) noexcept = default;
TimerBase& operator=(TimerBase&&) noexcept = default;
TimerHandle_t handle = NULL;
TickType_t deleteBlockTime;
};
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
/**
* Timer Timer.hpp <FreeRTOS/Timer.hpp>
*
* @brief Class that encapsulates the functionality of a FreeRTOS timer.
*
* Each software timer requires a small amount of RAM that is used to hold the
* timer's state. If a timer is created using this class then this RAM is
* automatically allocated from the FreeRTOS heap. If a software timer is
* created using FreeRTOS::StaticTimer() 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
* timerFunction().
*/
class Timer : public TimerBase {
public:
Timer(const Timer&) = delete;
Timer& operator=(const Timer&) = delete;
protected:
/**
* Timer.hpp
*
* @brief Construct a new Timer object by calling <tt>TimerHandle_t
* xTimerCreate( const char * const pcTimerName, const TickType_t
* xTimerPeriod, const UBaseType_t uxAutoReload, void * const pvTimerID,
* TimerCallbackFunction_t pxCallbackFunction )</tt>
*
* @see <https://www.freertos.org/FreeRTOS-timers-xTimerCreate.html>
*
* @warning The user should call isValid() on this object to verify that the
* timer was created successfully in case the memory required to create the
* timer could not be allocated.
*
* @note Timers are created in the dormant state. The start(), reset(),
* startFromISR(), resetFromISR(), changePeriod() and changePeriodFromISR()
* API functions can all be used to transition a timer into the active state.
*
* @note When calling <tt>xTimerCreate</tt> the constructor passes the
* <tt>this</tt> pointer as the pvTimerID argument. This pointer is used so
* that the interface function callTimerFunction() can invoke timerFunction()
* for this instance of the class.
*
* @param period The period of the timer. The period is specified in ticks,
* and the macro pdMS_TO_TICKS() can be used to convert a time specified in
* milliseconds to a time specified in ticks. For example, if the timer must
* expire after 100 ticks, then simply set period to 100. Alternatively, if
* the timer must expire after 500ms, then set period to pdMS_TO_TICKS( 500 ).
* pdMS_TO_TICKS() can only be used if configTICK_RATE_HZ is less than or
* equal to 1000. The timer period must be greater than 0.
* @param autoReload If autoReload is set to true, then the timer will expire
* repeatedly with a frequency set by the period parameter. If autoReload is
* set to false, then the timer will be a one-shot and enter the dormant state
* after it expires.
* @param name A human readable text name that is assigned to the timer. This
* is done purely to assist debugging. The RTOS kernel itself only ever
* references a timer by its handle, and never by its name.
* @param deleteBlockTime Specifies the time, in ticks, that the calling task
* should be held in the Blocked state to wait for the delete command to be
* successfully sent to the timer command queue, should the queue already be
* full when the destructor is called. deleteBlockTime is ignored if the
* destructor is called before the RTOS scheduler is started or if the timer
* has already been deleted by deleteTimer() before the destructor is called.
* This value can be updated by calling setDeleteBlockTime().
*
* <b>Example Usage</b>
* @include Timer/timer.cpp
*/
explicit Timer(const TickType_t period, const bool autoReload = false,
const char* name = "", const TickType_t deleteBlockTime = 0)
: TimerBase(deleteBlockTime) {
this->handle = xTimerCreate(name, period, (autoReload ? pdTRUE : pdFALSE),
this, callTimerFunction);
}
~Timer() = default;
Timer(Timer&&) noexcept = default;
Timer& operator=(Timer&&) noexcept = default;
};
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
#if (configSUPPORT_STATIC_ALLOCATION == 1)
/**
* Timer Timer.hpp <FreeRTOS/Timer.hpp>
*
* @brief Class that encapsulates the functionality of a FreeRTOS timer.
*
* Each software timer requires a small amount of RAM that is used to hold the
* timer's state. If a timer is created using FreeRTOS::Timer() then this RAM is
* automatically allocated from the FreeRTOS heap. If a software timer is
* created this class 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
* timerFunction().
*
* @warning This class contains the timer data structure, so any instance of
* this class or class derived from this class should be persistent (not
* declared on the stack of another function).
*/
class StaticTimer : public TimerBase {
public:
StaticTimer(const StaticTimer&) = delete;
StaticTimer& operator=(const StaticTimer&) = delete;
protected:
/**
* Timer.hpp
*
* @brief Construct a new StaticTimer object by calling <tt>TimerHandle_t
* xTimerCreateStatic( const char * const pcTimerName, const TickType_t
* xTimerPeriod, const UBaseType_t uxAutoReload, void * const pvTimerID,
* TimerCallbackFunction_t pxCallbackFunction StaticTimer_t *pxTimerBuffer
* )</tt>
*
* @see <https://www.freertos.org/xTimerCreateStatic.html>
*
* @note When calling <tt>xTimerCreateStatic</tt> the constructor passes the
* <tt>this</tt> pointer as the pvTimerID argument. This pointer is used so
* that the interface function callTimerFunction() can invoke timerFunction()
* for this instance of the class.
*
* @note Timers are created in the dormant state. The start(), reset(),
* startFromISR(), resetFromISR(), changePeriod() and changePeriodFromISR()
* API functions can all be used to transition a timer into the active state.
*
* @param period The period of the timer. The period is specified in ticks,
* and the macro pdMS_TO_TICKS() can be used to convert a time specified in
* milliseconds to a time specified in ticks. For example, if the timer must
* expire after 100 ticks, then simply set period to 100. Alternatively, if
* the timer must expire after 500ms, then set period to pdMS_TO_TICKS( 500 ).
* pdMS_TO_TICKS() can only be used if configTICK_RATE_HZ is less than or
* equal to 1000. The timer period must be greater than 0.
* @param autoReload If autoReload is set to true, then the timer will expire
* repeatedly with a frequency set by the period parameter. If autoReload is
* set to false, then the timer will be a one-shot and enter the dormant state
* after it expires.
* @param name A human readable text name that is assigned to the timer. This
* is done purely to assist debugging. The RTOS kernel itself only ever
* references a timer by its handle, and never by its name.
* @param deleteBlockTime Specifies the time, in ticks, that the calling task
* should be held in the Blocked state to wait for the delete command to be
* successfully sent to the timer command queue, should the queue already be
* full when the destructor is called. deleteBlockTime is ignored if the
* destructor is called before the RTOS scheduler is started or if the timer
* has already been deleted by deleteTimer() before the destructor is called.
* This value can be updated by calling setDeleteBlockTime().
*
* <b>Example Usage</b>
* @include Timer/staticTimer.cpp
*/
explicit StaticTimer(const TickType_t period, const bool autoReload = false,
const char* name = "",
const TickType_t deleteBlockTime = 0)
: TimerBase(deleteBlockTime) {
this->handle =
xTimerCreateStatic(name, period, (autoReload ? pdTRUE : pdFALSE), this,
callTimerFunction, &staticTimer);
}
~StaticTimer() = default;
StaticTimer(StaticTimer&&) noexcept = default;
StaticTimer& operator=(StaticTimer&&) noexcept = default;
private:
StaticTimer_t staticTimer;
};
#endif /* configSUPPORT_STATIC_ALLOCATION */
} // namespace FreeRTOS
inline void callTimerFunction(TimerHandle_t timer) {
static_cast<FreeRTOS::TimerBase*>(pvTimerGetTimerID(timer))->timerEntry();
}
#endif // FREERTOS_TIMER_HPP