tin  1.5.9
freertos.h
Go to the documentation of this file.
1 // Copyright (c) 2026 Tinverse LLC. All rights reserved.
2 // SPDX-License-Identifier: LicenseRef-Tinverse-Commercial
3 
9 
10 #pragma once
11 
12 #include <chrono>
13 #include <cstddef>
14 #include <type_traits>
15 #include <utility>
16 
17 #include "tsm/runtime/executor.h"
19 
20 #include "FreeRTOS.h"
21 #include "queue.h"
22 #include "task.h"
23 
24 constexpr int MaxEvents = 10; // Define your own queue size
25 
27 
33 template<std::size_t Capacity>
35 {
36  static constexpr std::size_t capacity = Capacity;
37 
38  template<typename Event>
39  class queue
40  {
41  static_assert(Capacity > 0,
42  "tsm: freertos_queue requires non-zero capacity");
43 
44  public:
45  using value_type = Event;
46 
48  : handle_(xQueueCreate(Capacity, sizeof(Event)))
49  {
50  configASSERT(handle_ != nullptr);
51  }
52 
53  queue(queue const&) = delete;
54  queue& operator=(queue const&) = delete;
55 
57  {
58  if (handle_ != nullptr) {
59  vQueueDelete(handle_);
60  }
61  }
62 
63  [[nodiscard]] bool try_push(Event const& event)
64  {
65  return xQueueSendToBack(handle_, &event, 0) == pdTRUE;
66  }
67 
68  [[nodiscard]] bool try_push(Event&& event)
69  {
70  return xQueueSendToBack(handle_, &event, 0) == pdTRUE;
71  }
72 
73  [[nodiscard]] bool try_pop(Event& event)
74  {
75  return xQueueReceive(handle_, &event, 0) == pdTRUE;
76  }
77 
78  [[nodiscard]] bool empty() const
79  {
80  return uxQueueMessagesWaiting(handle_) == 0;
81  }
82 
83  [[nodiscard]] bool full() const
84  {
85  return uxQueueSpacesAvailable(handle_) == 0;
86  }
87 
88  [[nodiscard]] std::size_t size() const
89  {
90  return uxQueueMessagesWaiting(handle_);
91  }
92 
93  [[nodiscard]] QueueHandle_t native_handle() const
94  {
95  return handle_;
96  }
97 
98  private:
99  QueueHandle_t handle_{};
100  };
101 };
102 
107 template<std::size_t Capacity>
109 {
111 };
112 
113 } // namespace tsm::runtime::storage
114 
115 namespace tsm {
116 
122 {
123  using duration = std::chrono::milliseconds;
124  using period = duration::period;
125  using rep = duration::rep;
126  using time_point = std::chrono::time_point<FreeRTOSClock>;
127 
128  static constexpr bool is_steady = true;
129 
130  static time_point now() noexcept
131  {
132  TickType_t ticks = xTaskGetTickCount();
133  auto elapsed =
134  std::chrono::milliseconds(ticks * (1000 / configTICK_RATE_HZ));
135  return time_point(duration(elapsed));
136  }
137 };
138 
140 {
141  [[nodiscard]] tsm::tick_rep ticks() const noexcept
142  {
143  return static_cast<tsm::tick_rep>(xTaskGetTickCount());
144  }
145 };
146 
152 template<typename... Tasks>
154 {
155  public:
156  explicit freertos_task_executor(Tasks&... tasks)
157  : ready_(tasks...)
158  {
159  }
160 
163 
165  {
166  stop();
167  }
168 
169  void start(char const* name = "tsm_exec",
170  uint16_t stack_depth = configMINIMAL_STACK_SIZE,
171  UBaseType_t priority = tskIDLE_PRIORITY + 1U)
172  {
173  if (task_handle_ != nullptr) {
174  return;
175  }
176  stop_requested_ = pdFALSE;
177  xTaskCreate(
178  task_entry, name, stack_depth, this, priority, &task_handle_);
179  }
180 
181  void stop()
182  {
183  stop_requested_ = pdTRUE;
184  wake();
185  if (task_handle_ != nullptr) {
186  vTaskDelete(task_handle_);
187  task_handle_ = nullptr;
188  }
189  }
190 
191  void wake()
192  {
193  if (task_handle_ != nullptr) {
194  // Task notification is only a wake surface. Event storage remains
195  // in the selected runtime queue topology.
196  xTaskNotifyGive(task_handle_);
197  }
198  }
199 
201  {
202  if (task_handle_ != nullptr) {
203  BaseType_t higher_priority_task_woken = pdFALSE;
204  vTaskNotifyGiveFromISR(task_handle_, &higher_priority_task_woken);
205  portYIELD_FROM_ISR(higher_priority_task_woken);
206  }
207  }
208 
210  {
211  static_cast<void>(ulTaskNotifyTake(pdTRUE, 1));
212  }
213 
214  [[nodiscard]] bool step()
215  {
216  return ready_.step();
217  }
218 
219  std::size_t run_ready()
220  {
221  return ready_.run_ready();
222  }
223 
224  std::size_t tick(tsm::tick_rep elapsed_ticks = 1U)
225  {
226  const auto resumed = ready_.tick(elapsed_ticks);
227  if (resumed != 0U) {
228  wake();
229  }
230  return resumed;
231  }
232 
233  std::size_t tick(tsm::tick_count elapsed_ticks)
234  {
235  return tick(elapsed_ticks.count());
236  }
237 
238  void start_all()
239  {
240  ready_.start_all();
241  }
242 
243  template<auto Entry, std::size_t Instance = 0U>
244  [[nodiscard]] spawn_result start()
245  {
246  auto result = ready_.template start<Entry, Instance>();
247  if (result == spawn_result::started) {
248  wake();
249  }
250  return result;
251  }
252 
253  template<auto Entry, typename... Args>
254  [[nodiscard]] spawn_result spawn(Args&&... args)
255  {
256  auto result = ready_.template spawn<Entry>(std::forward<Args>(args)...);
257  if (result == spawn_result::started) {
258  wake();
259  }
260  return result;
261  }
262 
264  {
266  }
267 
268  template<auto Entry, std::size_t Instance = 0U>
269  [[nodiscard]] task_status task_status() const
270  {
271  return ready_.template task_status<Entry, Instance>();
272  }
273 
274  template<auto Entry, std::size_t Instance = 0U>
276  {
278  }
279 
280  template<auto Entry, std::size_t Instance = 0U>
281  [[nodiscard]] bool cancel() noexcept
282  {
283  const bool cancelled = ready_.template cancel<Entry, Instance>();
284  if (cancelled) {
285  wake();
286  }
287  return cancelled;
288  }
289 
290  void cancel_all() noexcept
291  {
292  ready_.cancel_all();
293  wake();
294  }
295 
296  protected:
298  TaskHandle_t task_handle_{};
299  BaseType_t stop_requested_{ pdTRUE };
300 
301  static void task_entry(void* pv_parameters)
302  {
303  auto* executor = static_cast<freertos_task_executor*>(pv_parameters);
304  executor->run_task();
305  }
306 
307  void run_task()
308  {
309  while (!stop_requested_) {
310  if (ready_.run_ready() == 0U) {
311  // No cooperative work is ready, so the executor task blocks
312  // briefly until an event, spawned task, or tick wakes it.
313  wait_for_work();
314  }
315  }
316  }
317 };
318 
319 template<typename... Tasks>
321 
322 template<typename... Tasks>
323 using task_executor = freertos_task_executor<Tasks...>;
324 
325 } // namespace tsm
Definition: bare_metal.h:53
Definition: freertos.h:154
void start_all()
Definition: freertos.h:238
void wake_from_isr()
Definition: freertos.h:200
freertos_task_executor(Tasks &... tasks)
Definition: freertos.h:156
freertos_task_executor(freertos_task_executor const &)=delete
spawn_result spawn(Args &&... args)
Definition: freertos.h:254
bool step()
Definition: freertos.h:214
task_failure_reason task_failure_reason() const
Definition: freertos.h:275
~freertos_task_executor()
Definition: freertos.h:164
runtime::task_spawner< freertos_task_executor > spawner()
Definition: freertos.h:263
std::size_t tick(tsm::tick_rep elapsed_ticks=1U)
Definition: freertos.h:224
void start(char const *name="tsm_exec", uint16_t stack_depth=configMINIMAL_STACK_SIZE, UBaseType_t priority=tskIDLE_PRIORITY+1U)
Definition: freertos.h:169
static void task_entry(void *pv_parameters)
Definition: freertos.h:301
bool cancel() noexcept
Definition: freertos.h:281
void wait_for_work()
Definition: freertos.h:209
tsm::runtime::cooperative_executor< Tasks... > ready_
Definition: freertos.h:297
std::size_t tick(tsm::tick_count elapsed_ticks)
Definition: freertos.h:233
void wake()
Definition: freertos.h:191
void cancel_all() noexcept
Definition: freertos.h:290
spawn_result start()
Definition: freertos.h:244
TaskHandle_t task_handle_
Definition: freertos.h:298
task_status task_status() const
Definition: freertos.h:269
void stop()
Definition: freertos.h:181
void run_task()
Definition: freertos.h:307
freertos_task_executor & operator=(freertos_task_executor const &)=delete
std::size_t run_ready()
Definition: freertos.h:219
BaseType_t stop_requested_
Definition: freertos.h:299
void start_all()
Definition: executor.h:197
bool step()
Definition: executor.h:161
std::size_t tick(tsm::tick_rep elapsed_ticks=1U)
Definition: executor.h:181
void cancel_all() noexcept
Definition: executor.h:276
std::size_t run_ready()
Definition: executor.h:172
Definition: executor.h:294
Event value_type
Definition: freertos.h:45
queue & operator=(queue const &)=delete
bool try_pop(Event &event)
Definition: freertos.h:73
bool empty() const
Definition: freertos.h:78
bool try_push(Event &&event)
Definition: freertos.h:68
bool full() const
Definition: freertos.h:83
QueueHandle_t native_handle() const
Definition: freertos.h:93
std::size_t size() const
Definition: freertos.h:88
bool try_push(Event const &event)
Definition: freertos.h:63
Definition: executor.h:132
Target-independent executors for tsm runtimes.
constexpr int MaxEvents
Definition: freertos.h:24
Definition: freertos.h:26
Definition: bare_metal.h:20
task_failure_reason
Definition: coroutine.h:170
constexpr tick_count ticks(tick_rep value) noexcept
Definition: ticks.h:85
task_status
Definition: coroutine.h:160
freertos_task_executor(Tasks &...) -> freertos_task_executor< Tasks... >
spawn_result
Definition: coroutine.h:181
TSM_TICK_REP tick_rep
Definition: ticks.h:35
Fixed-capacity ring queue storage for runtime events.
Definition: freertos.h:122
std::chrono::time_point< FreeRTOSClock > time_point
Definition: freertos.h:126
static constexpr bool is_steady
Definition: freertos.h:128
std::chrono::milliseconds duration
Definition: freertos.h:123
duration::rep rep
Definition: freertos.h:125
static time_point now() noexcept
Definition: freertos.h:130
duration::period period
Definition: freertos.h:124
Definition: freertos.h:140
tsm::tick_rep ticks() const noexcept
Definition: freertos.h:141
Definition: freertos.h:35
static constexpr std::size_t capacity
Definition: freertos.h:36
Definition: static_ring.h:141
Definition: static_ring.h:154
Definition: coroutine.h:1162
Strong value type for semantic scheduler ticks.
Definition: ticks.h:54
constexpr tick_rep count() const noexcept
Definition: ticks.h:73