SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::time::TimerHost Class Reference

Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kernel tasks. More...

#include <stk_time_timer.h>

Collaboration diagram for stk::time::TimerHost:

Classes

class  Timer
 Abstract base class for a timer managed by TimerHost. More...
class  TimerWorkerTask
 The actual task that executes timer callback. More...
struct  TimerCommand

Public Types

enum  EConsts {
  TASK_COUNT = (1 + 1 ) ,
  TASK_TICK_MEMORY_SIZE = stk::Max<size_t>(256U, STK_STACK_SIZE_MIN) ,
  TASK_HANDLER_STACK_SIZE = stk::Max<size_t>( 256 , STK_STACK_SIZE_MIN)
}

Public Member Functions

 TimerHost ()
 ~TimerHost ()
 Destructor.
void Initialize (IKernel *kernel, EAccessMode mode)
 Initialize timer host instance.
bool Start (Timer &timer, uint32_t delay, uint32_t period=0)
 Start timer.
bool Stop (Timer &timer)
 Stop running timer.
bool Reset (Timer &timer)
 Reset periodic timer's deadline.
bool Restart (Timer &timer, uint32_t delay, uint32_t period=0)
 Atomically stop and re-start timer.
bool StartOrReset (Timer &timer, uint32_t delay, uint32_t period=0)
 Start timer if inactive, or reset its deadline if already active and periodic.
bool SetPeriod (Timer &timer, uint32_t period)
 Change the period of a running periodic timer without affecting its current deadline.
bool IsEmpty () const
 Return true if no timers are currently active.
size_t GetSize () const
 Return number of currently active timers.
bool Shutdown ()
 Shutdown host instance. All timers are stopped and removed from the host.
Ticks GetTimeNow () const
 Get current time.

Private Types

typedef void(* TimerFuncType) (TimerHost *host)
 Timer task function prototype.
typedef StackMemoryDef< TASK_TICK_MEMORY_SIZE >::Type TaskTickMemory
typedef StackMemoryDef< TASK_HANDLER_STACK_SIZE >::Type TimerHostMemory
typedef sync::Pipe< Timer *, 32 > ReadyQueue
typedef sync::Pipe< TimerCommand, 32 > CommandQueue

Private Member Functions

 STK_NONCOPYABLE_CLASS (TimerHost)
void UpdateTime ()
void ProcessTimers ()
bool ProcessCommands (Timeout next_sleep)
bool PushCommand (TimerCommand cmd)

Private Attributes

TaskTickMemory m_task_tick_memory
 tick task memory
TimerHostMemory m_task_handler_memory [1]
 handler task memory
TimerWorkerTask m_task_tick
 timer task
TimerWorkerTask m_task_process [1]
 handler tasks
util::DListHead< Timer, false > m_active
 active timers (tick task only)
ReadyQueue m_queue
 queue of timers ready for handling
CommandQueue m_commands
 command queue
Ticks m_now
 last known current time (ticks)

Detailed Description

Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kernel tasks.

TimerHost internally runs two categories of tasks:

  • One tick task that maintains the active timer list, evaluates deadlines every wake cycle, and queues expired timers for dispatch.
  • One or more handler tasks (see STK_TIMER_THREADS_COUNT) that dequeue expired timers and invoke their OnExpired() callbacks.

All timers share the same tick and handler tasks, so the total kernel task overhead is constant regardless of how many timers are active.

Two timer modes are supported:

  • One-shot: fires once after delay ticks and becomes inactive automatically.
  • Periodic: fires every period ticks until explicitly stopped.
Note
TimerHost must be initialized before use by calling Initialize(). The maximum number of concurrently active timers is STK_TIMER_COUNT_MAX (default: 32). The maximum timer period is bounded by uint32_t (~49 days at 1 ms resolution).
// define a concrete timer by overriding OnExpired
class HeartbeatTimer : public stk::time::TimerHost::Timer
{
public:
{
// called every 500 ms
ToggleLed();
}
};
// declare host and timer instances (static storage, no heap)
HeartbeatTimer g_Heartbeat;
// one-shot example: send a delayed notification
class NotifyTimer : public stk::time::TimerHost::Timer
{
public:
{
g_Event.Signal();
}
};
NotifyTimer g_Notify;
void SetupTimers(stk::IKernel *kernel)
{
// initialize the host, must be called before Start()
g_TimerHost.Initialize(kernel, stk::ACCESS_USER);
// start 500 ms periodic heartbeat
uint32_t period = stk::GetTicksFromMsec(500);
g_TimerHost.Start(g_Heartbeat, period, period);
// start a one-shot notification after 1 second
uint32_t delay = stk::GetTicksFromMsec(1000);
g_TimerHost.Start(g_Notify, delay);
}
@ ACCESS_USER
Unprivileged access mode (access to some hardware is restricted, see CPU manual for details).
Definition stk_common.h:32
Software timer multiplexer that manages multiple Timer instances on top of a small fixed set of kerne...
void Initialize(IKernel *kernel, EAccessMode mode)
Initialize timer host instance.
bool Start(Timer &timer, uint32_t delay, uint32_t period=0)
Start timer.
Abstract base class for a timer managed by TimerHost.
virtual void OnExpired(TimerHost *host)=0
See also
TimerHost::Timer, STK_TIMER_THREADS_COUNT, STK_TIMER_HANDLER_STACK_SIZE, STK_TIMER_COUNT_MAX

Definition at line 111 of file stk_time_timer.h.

Member Typedef Documentation

◆ CommandQueue

Definition at line 354 of file stk_time_timer.h.

◆ ReadyQueue

Definition at line 353 of file stk_time_timer.h.

◆ TaskTickMemory

◆ TimerFuncType

typedef void(* stk::time::TimerHost::TimerFuncType) (TimerHost *host)
private

Timer task function prototype.

Definition at line 279 of file stk_time_timer.h.

◆ TimerHostMemory

Member Enumeration Documentation

◆ EConsts

Enumerator
TASK_COUNT 

total number of tasks serving this instance

stack memory size of the tick task

TASK_TICK_MEMORY_SIZE 

stack memory size of the timer handler task

TASK_HANDLER_STACK_SIZE 

Definition at line 114 of file stk_time_timer.h.

115 {
118
121
124 };
#define STK_STACK_SIZE_MIN
Minimum stack size in elements of Word, shared by all stack allocation lower-bound checks.
Definition stk_defs.h:454
#define STK_TIMER_THREADS_COUNT
Number of threads handling timers in TimerHost (default: 1).
#define STK_TIMER_HANDLER_STACK_SIZE
Stack size of the timer handler, increase if your timers consume more (default: 256).
constexpr T Max(T a, T b) noexcept
Compile-time maximum of two values.
Definition stk_defs.h:536
@ TASK_TICK_MEMORY_SIZE
stack memory size of the timer handler task
@ TASK_COUNT
total number of tasks serving this instance

Constructor & Destructor Documentation

◆ TimerHost()

stk::time::TimerHost::TimerHost ( )
inlineexplicit

Definition at line 176 of file stk_time_timer.h.

178 {}
Ticks m_now
last known current time (ticks)
util::DListHead< Timer, false > m_active
active timers (tick task only)
TimerWorkerTask m_task_tick
timer task
TimerWorkerTask m_task_process[1]
handler tasks
TaskTickMemory m_task_tick_memory
tick task memory
TimerHostMemory m_task_handler_memory[1]
handler task memory

References m_active, m_now, m_task_handler_memory, m_task_process, m_task_tick, and m_task_tick_memory.

Referenced by Initialize(), stk::time::TimerHost::TimerWorkerTask::Initialize(), and STK_NONCOPYABLE_CLASS().

Here is the caller graph for this function:

◆ ~TimerHost()

stk::time::TimerHost::~TimerHost ( )
inline

Destructor.

Note
MISRA deviation: [STK-DEV-005] Rule 10-3-2.

Definition at line 183 of file stk_time_timer.h.

184 {}

Member Function Documentation

◆ GetSize()

size_t stk::time::TimerHost::GetSize ( ) const
inline

Return number of currently active timers.

Returns
Active timer count.
Note
The value is advisory and may change immediately after the call.

Definition at line 261 of file stk_time_timer.h.

261{ return m_active.GetSize(); }

References m_active.

Referenced by stk_timerhost_get_size().

Here is the caller graph for this function:

◆ GetTimeNow()

Ticks stk::time::TimerHost::GetTimeNow ( ) const
inline

Get current time.

Returns
Current time (ticks).

Definition at line 271 of file stk_time_timer.h.

271{ return hw::ReadVolatile64(&m_now); }
__stk_forceinline T ReadVolatile64(volatile const T *addr)
Atomically read a 64-bit volatile value.
Definition stk_arch.h:357

References m_now, and stk::hw::ReadVolatile64().

Referenced by stk_timerhost_get_time_now().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Initialize()

void stk::time::TimerHost::Initialize ( IKernel * kernel,
EAccessMode mode )
inline

Initialize timer host instance.

Parameters
[in]kernelKernel to which instance will be bound.
[in]modeAccess mode for the timer handling tasks which call expired timers.

Definition at line 386 of file stk_time_timer.h.

387{
388 for (int32_t i = 0; i < STK_TIMER_THREADS_COUNT; ++i)
389 {
390 m_task_process[i].Initialize(this, m_task_handler_memory[i], TASK_HANDLER_STACK_SIZE, mode, [](TimerHost *host) {
391 host->ProcessTimers();
392 });
393 kernel->AddTask(&m_task_process[i]);
394 }
395
397 host->UpdateTime();
398 });
399 kernel->AddTask(&m_task_tick);
400}

References stk::ACCESS_USER, stk::IKernel::AddTask(), m_task_handler_memory, m_task_process, m_task_tick, m_task_tick_memory, ProcessTimers(), STK_TIMER_THREADS_COUNT, TASK_HANDLER_STACK_SIZE, TASK_TICK_MEMORY_SIZE, TimerHost(), and UpdateTime().

Referenced by stk_timerhost_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsEmpty()

bool stk::time::TimerHost::IsEmpty ( ) const
inline

Return true if no timers are currently active.

Returns
True if active timer count is zero.
Note
The value is advisory and may change immediately after the call.

Definition at line 255 of file stk_time_timer.h.

255{ return m_active.IsEmpty(); }

References m_active.

Referenced by stk_timerhost_is_empty().

Here is the caller graph for this function:

◆ ProcessCommands()

bool stk::time::TimerHost::ProcessCommands ( Timeout next_sleep)
inlineprivate

Definition at line 652 of file stk_time_timer.h.

653{
654 // if nothing is active, sleep indefinitely until a command arrives
655 next_sleep = (m_active.IsEmpty() ? WAIT_INFINITE : next_sleep);
656
657 TimerCommand cmd;
658 while (m_commands.Read(cmd, next_sleep))
659 {
660 switch (cmd.cmd)
661 {
663 Timer *timer = cmd.timer;
664 STK_ASSERT(timer != nullptr);
665
666 // reject if already active or linked (double-start)
667 if (timer->m_active)
668 continue;
669
670 STK_ASSERT(!timer->IsLinked());
671
672 timer->m_deadline = cmd.timestamp + cmd.delay;
673 timer->m_period = cmd.period;
674 timer->m_active = true;
675 timer->m_pending = false;
676
677 m_active.LinkBack(timer);
678 next_sleep = NO_WAIT;
679 break; }
680
682 Timer *timer = cmd.timer;
683 STK_ASSERT(timer != nullptr);
684
685 timer->m_active = false;
686 timer->m_pending = false;
687
688 // allow possibly duplicate CMD_STOP as it is harmless for the logic
689 if (timer->IsLinked())
690 m_active.Unlink(timer);
691 break; }
692
694 Timer *timer = cmd.timer;
695 STK_ASSERT(timer != nullptr);
696
697 // only reset if still active and periodic
698 if (!timer->m_active || (timer->m_period == 0))
699 continue;
700
701 STK_ASSERT(timer->GetHead() == &m_active);
702
703 timer->m_deadline = cmd.timestamp + timer->m_period;
704 timer->m_pending = false;
705
706 next_sleep = NO_WAIT;
707 break; }
708
710 // atomic stop + re-start: no precondition on current timer state
711 Timer *timer = cmd.timer;
712 STK_ASSERT(timer != nullptr);
713
714 // unlink if currently in the active list
715 if (timer->IsLinked())
716 m_active.Unlink(timer);
717
718 // re-arm with fresh parameters
719 timer->m_deadline = cmd.timestamp + cmd.delay;
720 timer->m_period = cmd.period;
721 timer->m_active = true;
722 timer->m_pending = false;
723
724 // re-link to the back of the list
725 m_active.LinkBack(timer);
726 next_sleep = NO_WAIT;
727 break; }
728
730 Timer *timer = cmd.timer;
731 STK_ASSERT(timer != nullptr);
732
733 // not currently active: start with supplied parameters
734 if (!timer->m_active)
735 {
736 STK_ASSERT(!timer->IsLinked());
737
738 timer->m_deadline = cmd.timestamp + cmd.delay;
739 timer->m_period = cmd.period;
740 timer->m_active = true;
741 timer->m_pending = false;
742
743 m_active.LinkBack(timer);
744 }
745 else
746 // active and periodic: reset deadline anchored to call-site timestamp
747 if (timer->m_period != 0)
748 {
749 STK_ASSERT(timer->GetHead() == &m_active);
750
751 timer->m_deadline = cmd.timestamp + timer->m_period;
752 timer->m_pending = false;
753 }
754
755 // active one-shot: no action — cannot reset a one-shot mid-flight,
756 // caller should use Restart() if unconditional re-arm is needed.
757
758 next_sleep = NO_WAIT;
759 break; }
760
762 Timer *timer = cmd.timer;
763 STK_ASSERT(timer != nullptr);
764 STK_ASSERT(cmd.period != 0U);
765
766 // guard: only apply if still active and periodic
767 if (!timer->m_active || (timer->m_period == 0U))
768 continue;
769
770 STK_ASSERT(timer->GetHead() == &m_active);
771
772 // new period takes effect on the next reload, current deadline is
773 // intentionally left unchanged so the in-flight interval is not
774 // truncated or extended, caller can follow up with Reset() if
775 // immediate application is required
776 timer->m_period = cmd.period;
777 break; }
778
780 // wake all handler tasks with shutdown sentinels
781 for (int32_t i = 0; i < STK_TIMER_THREADS_COUNT; ++i)
782 m_queue.Write(nullptr, NO_WAIT);
783
784 // signal UpdateTime() to exit its loop
785 return false; }
786
787 default: {
788 STK_ASSERT(false);
789 break; }
790 }
791 }
792
793 return true;
794}
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
const Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:139
const Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:145
ReadyQueue m_queue
queue of timers ready for handling
CommandQueue m_commands
command queue
@ CMD_SET_PERIOD
change period of a running periodic timer
@ CMD_START_OR_RESET
start if inactive, reset deadline if active and periodic
@ CMD_RESTART
atomic stop + re-start

References stk::time::TimerHost::TimerCommand::cmd, stk::time::TimerHost::TimerCommand::CMD_RESET, stk::time::TimerHost::TimerCommand::CMD_RESTART, stk::time::TimerHost::TimerCommand::CMD_SET_PERIOD, stk::time::TimerHost::TimerCommand::CMD_SHUTDOWN, stk::time::TimerHost::TimerCommand::CMD_START, stk::time::TimerHost::TimerCommand::CMD_START_OR_RESET, stk::time::TimerHost::TimerCommand::CMD_STOP, stk::time::TimerHost::TimerCommand::delay, stk::util::DListEntry< T, _ClosedLoop >::GetHead(), stk::util::DListEntry< T, _ClosedLoop >::IsLinked(), m_active, stk::time::TimerHost::Timer::m_active, m_commands, stk::time::TimerHost::Timer::m_deadline, stk::time::TimerHost::Timer::m_pending, stk::time::TimerHost::Timer::m_period, m_queue, stk::NO_WAIT, stk::time::TimerHost::TimerCommand::period, STK_ASSERT, STK_TIMER_THREADS_COUNT, stk::time::TimerHost::TimerCommand::timer, stk::time::TimerHost::TimerCommand::timestamp, and stk::WAIT_INFINITE.

Referenced by UpdateTime().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProcessTimers()

void stk::time::TimerHost::ProcessTimers ( )
inlineprivate

Definition at line 631 of file stk_time_timer.h.

632{
633 Timer *timer;
634 while (m_queue.Read(timer))
635 {
636 // nullptr is the shutdown sentinel pushed by CMD_SHUTDOWN
637 if (timer == nullptr)
638 break;
639
640 if (timer->m_pending)
641 {
642 timer->m_pending = false;
643 timer->OnExpired(this);
644 }
645 }
646}

References stk::time::TimerHost::Timer::m_pending, m_queue, and stk::time::TimerHost::Timer::OnExpired().

Referenced by Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ PushCommand()

bool stk::time::TimerHost::PushCommand ( TimerCommand cmd)
inlineprivate

Definition at line 800 of file stk_time_timer.h.

801{
802 if (!m_commands.Write(cmd, NO_WAIT))
803 {
804 // queue full: this indicates a usage error — more commands are being
805 // issued than the tick task can drain. Loud in debug, recoverable in
806 // release (caller receives false and can retry or escalate).
807 STK_ASSERT(false);
808 return false;
809 }
810
811 return true;
812}

References m_commands, stk::NO_WAIT, and STK_ASSERT.

Referenced by Reset(), Restart(), SetPeriod(), Shutdown(), Start(), StartOrReset(), and Stop().

Here is the caller graph for this function:

◆ Reset()

bool stk::time::TimerHost::Reset ( Timer & timer)
inline

Reset periodic timer's deadline.

Parameters
[in]timerTimer instance. Must be active and periodic.
Returns
True on success, false if timer is not active, not periodic, or command queue is full.

Definition at line 447 of file stk_time_timer.h.

448{
449 // timer must be active and periodic
450 if (!timer.m_active || (timer.m_period == 0))
451 return false;
452
453 return PushCommand({
455 .timer = &timer,
456 .timestamp = GetTicks(),
457 .delay = 0U,
458 .period = 0U
459 });
460}
Ticks GetTicks()
Get number of ticks elapsed since kernel start.
Definition stk_helper.h:248
bool PushCommand(TimerCommand cmd)

References stk::time::TimerHost::TimerCommand::CMD_RESET, stk::GetTicks(), stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_period, and PushCommand().

Referenced by stk_timer_reset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Restart()

bool stk::time::TimerHost::Restart ( Timer & timer,
uint32_t delay,
uint32_t period = 0 )
inline

Atomically stop and re-start timer.

Parameters
[in]timerTimer instance (active or inactive).
[in]delayInitial delay in ticks before first expiration.
[in]periodReload period in ticks (0 is one-shot timer).
Returns
True on success, false if command queue is full.
Note
Unlike calling Stop() followed by Start(), this operation is atomic with respect to the tick task: the timer cannot fire between the implicit stop and re-start, and only one command queue slot is consumed. Useful for watchdog refresh and debounce reset patterns. Safe to call regardless of whether the timer is currently active.

Definition at line 466 of file stk_time_timer.h.

467{
468 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
469 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
470
471 return PushCommand({
473 .timer = &timer,
474 .timestamp = GetTicks(),
475 .delay = delay,
476 .period = period
477 });
478}

References stk::time::TimerHost::TimerCommand::CMD_RESTART, stk::GetTicks(), PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_restart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetPeriod()

bool stk::time::TimerHost::SetPeriod ( Timer & timer,
uint32_t period )
inline

Change the period of a running periodic timer without affecting its current deadline.

Parameters
[in]timerTimer instance. Must be active and periodic.
[in]periodNew reload period in ticks. Must be non-zero.
Returns
True on success, false if timer is not active, not periodic, period is zero, or command queue is full.
Note
The new period takes effect on the next reload after the current deadline fires. To apply the new period immediately (restart from now), call Reset() after SetPeriod().

Definition at line 502 of file stk_time_timer.h.

503{
504 // period == 0 is rejected: it would silently convert a periodic timer
505 // to one-shot semantics, which is better expressed via Stop() + Start()
506 if (!timer.m_active || (timer.m_period == 0U) || (period == 0U) ||
507 (period > static_cast<uint32_t>(WAIT_INFINITE)))
508 {
509 return false;
510 }
511
512 return PushCommand({
514 .timer = &timer,
515 .timestamp = 0,
516 .delay = 0U,
517 .period = period
518 });
519}

References stk::time::TimerHost::TimerCommand::CMD_SET_PERIOD, stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_period, PushCommand(), and stk::WAIT_INFINITE.

Referenced by stk_timer_set_period().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Shutdown()

bool stk::time::TimerHost::Shutdown ( )
inline

Shutdown host instance. All timers are stopped and removed from the host.

Returns
True on success, false if command queue is full.

Definition at line 525 of file stk_time_timer.h.

526{
527 return PushCommand({
529 .timer = nullptr,
530 .timestamp = 0,
531 .delay = 0U,
532 .period = 0U
533 });
534}

References stk::time::TimerHost::TimerCommand::CMD_SHUTDOWN, and PushCommand().

Referenced by stk_timerhost_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Start()

bool stk::time::TimerHost::Start ( Timer & timer,
uint32_t delay,
uint32_t period = 0 )
inline

Start timer.

Parameters
[in]timerTimer instance. Must not already be active.
[in]delayInitial delay in ticks before first expiration.
[in]periodReload period in ticks (0 is one-shot timer).
Returns
True on success, false if timer is already active or command queue is full.

Definition at line 406 of file stk_time_timer.h.

407{
408 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
409 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
410
411 // timer must not already be active
412 if (timer.m_active)
413 return false;
414
415 return PushCommand({
417 .timer = &timer,
418 .timestamp = GetTicks(),
419 .delay = delay,
420 .period = period
421 });
422}

References stk::time::TimerHost::TimerCommand::CMD_START, stk::GetTicks(), stk::time::TimerHost::Timer::m_active, PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartOrReset()

bool stk::time::TimerHost::StartOrReset ( Timer & timer,
uint32_t delay,
uint32_t period = 0 )
inline

Start timer if inactive, or reset its deadline if already active and periodic.

Parameters
[in]timerTimer instance (active or inactive).
[in]delayInitial delay in ticks (used only when starting).
[in]periodReload period in ticks (used only when starting, 0 is one-shot).
Returns
True on success, false if command queue is full.
Note
Collapses the common pattern: if (timer.IsActive()) host.Reset(timer); else host.Start(timer, delay, period); into a single atomic operation, eliminating the TOCTOU race between the IsActive() check and the subsequent call. If the timer is active but one-shot, no action is taken (a one-shot timer mid-flight cannot be reset; use Restart() instead).

Definition at line 484 of file stk_time_timer.h.

485{
486 STK_ASSERT(delay <= static_cast<uint32_t>(WAIT_INFINITE));
487 STK_ASSERT((period == 0U) || (period <= static_cast<uint32_t>(WAIT_INFINITE)));
488
489 return PushCommand({
491 .timer = &timer,
492 .timestamp = GetTicks(),
493 .delay = delay,
494 .period = period
495 });
496}

References stk::time::TimerHost::TimerCommand::CMD_START_OR_RESET, stk::GetTicks(), PushCommand(), STK_ASSERT, and stk::WAIT_INFINITE.

Referenced by stk_timer_start_or_reset().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ STK_NONCOPYABLE_CLASS()

stk::time::TimerHost::STK_NONCOPYABLE_CLASS ( TimerHost )
private

References TimerHost().

Here is the call graph for this function:

◆ Stop()

bool stk::time::TimerHost::Stop ( Timer & timer)
inline

Stop running timer.

Parameters
[in]timerTimer instance. Must be active.
Returns
True on success, false if timer is not active or command queue is full.

Definition at line 428 of file stk_time_timer.h.

429{
430 // timer must be active
431 if (!timer.m_active)
432 return false;
433
434 return PushCommand({
436 .timer = &timer,
437 .timestamp = 0,
438 .delay = 0U,
439 .period = 0U
440 });
441}

References stk::time::TimerHost::TimerCommand::CMD_STOP, stk::time::TimerHost::Timer::m_active, and PushCommand().

Referenced by stk_timer_stop().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateTime()

void stk::time::TimerHost::UpdateTime ( )
inlineprivate

Definition at line 540 of file stk_time_timer.h.

541{
542 Timeout next_sleep = NO_WAIT;
543
544 while (ProcessCommands(next_sleep))
545 {
546 next_sleep = WAIT_INFINITE;
547
548 Ticks now = GetTicks();
549
550 // using WriteVolatile64() to guarantee correct lockless reading order by ReadVolatile64
552
553 Timer *timer = static_cast<Timer *>(m_active.GetFirst());
554 while (timer != nullptr)
555 {
556 Timer *next = static_cast<Timer *>(timer->GetNext());
557
558 if (timer->m_active)
559 {
560 // check if still pending to be handled
561 if (timer->m_pending)
562 {
563 timer = next;
564 continue;
565 }
566
567 bool one_shot = false;
568 Ticks diff = now - timer->m_deadline;
569
570 if (diff >= 0)
571 {
572 // set timestamp at which timer expired
573 timer->m_timestamp = now;
574
575 // avoid updating timer again before it was handled
576 timer->m_pending = true;
577
578 // periodic
579 if (timer->m_period != 0)
580 {
581 // reload (use now to avoid drift accumulation)
582 timer->m_deadline = now + static_cast<Ticks>(timer->m_period) - diff;
583 }
584 // one-shot
585 else
586 {
587 one_shot = true;
588
589 // remove from active timers
590 m_active.Unlink(timer);
591
592 // mark as inactive (must follow Unlink)
593 timer->m_active = false;
594 }
595
596 __stk_full_memfence();
597
598 // push to the handling queue
599 m_queue.Write(timer);
600 }
601
602 // one-shot timer does not affect next_sleep
603 if (!one_shot)
604 {
605 Timeout next_deadline = static_cast<Timeout>(timer->m_deadline - now);
606 STK_ASSERT(next_deadline > 0);
607
608 if ((next_deadline > 0) && (next_deadline < next_sleep))
609 next_sleep = next_deadline;
610 }
611 }
612 else
613 {
614 // could be stopped externally, remove from active timers
615 m_active.Unlink(timer);
616 }
617
618 timer = next;
619 }
620 }
621
622 // unlink all timers on shutdown
623 while (Timer::DLEntryType *timer = m_active.GetFirst())
624 m_active.Unlink(timer);
625}
int64_t Ticks
Ticks value.
Definition stk_common.h:150
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:133
__stk_forceinline void WriteVolatile64(volatile T *addr, T value)
Atomically write a 64-bit volatile value.
Definition stk_arch.h:411
DListEntry< Timer, _ClosedLoop > DLEntryType
bool ProcessCommands(Timeout next_sleep)

References stk::util::DListEntry< T, _ClosedLoop >::GetNext(), stk::GetTicks(), m_active, stk::time::TimerHost::Timer::m_active, stk::time::TimerHost::Timer::m_deadline, m_now, stk::time::TimerHost::Timer::m_pending, stk::time::TimerHost::Timer::m_period, m_queue, stk::time::TimerHost::Timer::m_timestamp, stk::NO_WAIT, ProcessCommands(), STK_ASSERT, stk::WAIT_INFINITE, and stk::hw::WriteVolatile64().

Referenced by Initialize().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_active

util::DListHead<Timer, false> stk::time::TimerHost::m_active
private

active timers (tick task only)

Definition at line 360 of file stk_time_timer.h.

Referenced by GetSize(), IsEmpty(), ProcessCommands(), TimerHost(), and UpdateTime().

◆ m_commands

CommandQueue stk::time::TimerHost::m_commands
private

command queue

Definition at line 362 of file stk_time_timer.h.

Referenced by ProcessCommands(), and PushCommand().

◆ m_now

Ticks stk::time::TimerHost::m_now
private

last known current time (ticks)

Definition at line 363 of file stk_time_timer.h.

Referenced by GetTimeNow(), TimerHost(), and UpdateTime().

◆ m_queue

ReadyQueue stk::time::TimerHost::m_queue
private

queue of timers ready for handling

Definition at line 361 of file stk_time_timer.h.

Referenced by ProcessCommands(), ProcessTimers(), and UpdateTime().

◆ m_task_handler_memory

TimerHostMemory stk::time::TimerHost::m_task_handler_memory[1]
private

handler task memory

Definition at line 357 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_process

TimerWorkerTask stk::time::TimerHost::m_task_process[1]
private

handler tasks

Definition at line 359 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_tick

TimerWorkerTask stk::time::TimerHost::m_task_tick
private

timer task

Definition at line 358 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().

◆ m_task_tick_memory

TaskTickMemory stk::time::TimerHost::m_task_tick_memory
private

tick task memory

Definition at line 356 of file stk_time_timer.h.

Referenced by Initialize(), and TimerHost().


The documentation for this class was generated from the following file: