blob: 6633d1e00e3abab527a3fb3b6420210e2feaebe3 [file] [log] [blame]
Ewout van Bekkum749342b2021-01-19 14:53:19 -08001.. _module-pw_thread_freertos:
2
Ewout van Bekkumb9b1d362021-05-14 17:16:07 -07003==================
Ewout van Bekkum749342b2021-01-19 14:53:19 -08004pw_thread_freertos
Ewout van Bekkumb9b1d362021-05-14 17:16:07 -07005==================
6This is a set of backends for pw_thread based on FreeRTOS.
Ewout van Bekkum749342b2021-01-19 14:53:19 -08007
Ewout van Bekkumb9b1d362021-05-14 17:16:07 -07008.. contents::
9 :local:
10 :depth: 1
11
12.. Warning::
13 This module is still under construction, the API is not yet stable.
14
15-----------------------
16Thread Creation Backend
17-----------------------
18A backend for ``pw::thread::Thread`` is offered using ``xTaskCreateStatic()``.
19Optional dynamic allocation for threads is supported using ``xTaskCreate()``.
20Optional joining support is enabled via an ``StaticEventGroup_t`` in each
21thread's context.
22
23This backend always permits users to start threads where static contexts are
24passed in as an option. As a quick example, a detached thread can be created as
25follows:
26
27.. code-block:: cpp
28
29 #include "FreeRTOS.h"
30 #include "pw_thread/detached_thread.h"
31 #include "pw_thread_freertos/context.h"
32 #include "pw_thread_freertos/options.h"
33
34 pw::thread::freertos::StaticContextWithStack<42> example_thread_context;
35 void StartExampleThread() {
36 pw::thread::DetachedThread(
37 pw::thread::freertos::Options()
38 .set_name("static_example_thread")
39 .set_priority(kFooPriority)
40 .set_static_context(example_thread_context),
41 example_thread_function)
42 }
43
44Alternatively when ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is
45enabled, dynamic thread allocation can be used. The above example could instead
46be done as follows:
47
48.. code-block:: cpp
49
50 #include "FreeRTOS.h"
51 #include "pw_thread/detached_thread.h"
52 #include "pw_thread_freertos/context.h"
53 #include "pw_thread_freertos/options.h"
54
55 void StartExampleThread() {
56 pw::thread::DetachedThread(
57 pw::thread::freertos::Options()
58 .set_name("dyanmic_example_thread")
59 .set_priority(kFooPriority)
60 .set_stack_size(42),
61 example_thread_function)
62 }
63
64
65Module Configuration Options
66============================
67The following configurations can be adjusted via compile-time configuration of
68this module, see the
69:ref:`module documentation <module-structure-compile-time-configuration>` for
70more details.
71
72.. c:macro:: PW_THREAD_FREERTOS_CONFIG_JOINING_ENABLED
73
74 Whether thread joining is enabled. By default this is disabled.
75
76 We suggest only enabling this when thread joining is required to minimize
77 the RAM and ROM cost of threads.
78
79 Enabling this grows the RAM footprint of every ``pw::thread::Thread`` as it
80 adds a ``StaticEventGroup_t`` to every thread's
81 ``pw::thread::freertos::Context``. In addition, there is a minute ROM cost to
82 construct and destroy this added object.
83
84 ``PW_THREAD_JOINING_ENABLED`` gets set to this value.
85
86.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED
87
88 Whether dynamic allocation for threads (stacks and contexts) is enabled. By
89 default this matches the FreeRTOS configuration on whether dynamic
90 allocations are enabled. Note that static contexts **must** be provided if
91 dynamic allocations are disabled.
92
93.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_STACK_SIZE_WORDS
94
95 The default stack size in words. By default this uses the minimal FreeRTOS
96 stack size based on ``configMINIMAL_STACK_SIZE``.
97
98.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_PRIORITY
99
100 The default stack size in words. By default this uses the minimal FreeRTOS
101 priority level above the idle priority (``tskIDLE_PRIORITY + 1``).
102
103FreeRTOS Thread Options
104=======================
105.. cpp:class:: pw::thread::freertos::Options
106
107 .. cpp:function:: set_name(const char* name)
108
109 Sets the name for the FreeRTOS task, note that this will be truncated
110 based on ``configMAX_TASK_NAME_LEN``. This is deep copied by FreeRTOS into
111 the task's task control block (TCB).
112
113 .. cpp:function:: set_priority(UBaseType_t priority)
114
115 Sets the priority for the FreeRTOS task. This must be a value between
116 ``tskIDLE_PRIORITY`` or ``0`` to ``configMAX_PRIORITIES - 1``. Higher
117 priority values have a higher priority.
118
119 .. cpp:function:: set_stack_size(size_t size_words)
120
121 Set the stack size in words for a dynamically thread.
122
123 This is only available if
124 ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is enabled.
125
126 Precondition: size_words must be >= ``configMINIMAL_STACK_SIZE``
127
128 .. cpp:function:: set_static_context(pw::thread::freertos::Context& context)
129
130 Set the pre-allocated context (all memory needed to run a thread). The
131 ``StaticContext`` can either be constructed with an externally provided
132 ``std::span<StackType_t>`` stack or the templated form of
133 ``StaticContextWithStack<kStackSizeWords>`` can be used.
134
135
136-----------------------------
137Thread Identification Backend
138-----------------------------
139A backend for ``pw::thread::Id`` and ``pw::thread::get_id()`` is offerred using
140``xTaskGetCurrentTaskHandle()``. It uses ``DASSERT`` to ensure that it is not
141invoked from interrupt context and if possible that the scheduler has started
142via ``xTaskGetSchedulerState()``.
143
144--------------------
145Thread Sleep Backend
146--------------------
147A backend for ``pw::thread::sleep_for()`` and ``pw::thread::sleep_until()`` is
148offerred using ``vTaskDelay()`` if the duration is at least one tick, else
149``taskYIELD()`` is used. It uses ``pw::this_thread::get_id() != thread::Id()``
150to ensure it invoked only from a thread.
151
152--------------------
153Thread Yield Backend
154--------------------
155A backend for ``pw::thread::yield()`` is offered using via ``taskYIELD()``.
156It uses ``pw::this_thread::get_id() != thread::Id()`` to ensure it invoked only
157from a thread.