xref: /aosp_15_r20/external/pigweed/pw_thread_freertos/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_thread_freertos:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker==================
4*61c4878aSAndroid Build Coastguard Workerpw_thread_freertos
5*61c4878aSAndroid Build Coastguard Worker==================
6*61c4878aSAndroid Build Coastguard WorkerThis is a set of backends for pw_thread based on FreeRTOS.
7*61c4878aSAndroid Build Coastguard Worker
8*61c4878aSAndroid Build Coastguard Worker.. Warning::
9*61c4878aSAndroid Build Coastguard Worker  This module is still under construction, the API is not yet stable.
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker-----------------------
12*61c4878aSAndroid Build Coastguard WorkerThread Creation Backend
13*61c4878aSAndroid Build Coastguard Worker-----------------------
14*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::Thread`` is offered using ``xTaskCreateStatic()``.
15*61c4878aSAndroid Build Coastguard WorkerOptional dynamic allocation for threads is supported using ``xTaskCreate()``.
16*61c4878aSAndroid Build Coastguard WorkerOptional joining support is enabled via an ``StaticEventGroup_t`` in each
17*61c4878aSAndroid Build Coastguard Workerthread's context.
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker.. Note::
20*61c4878aSAndroid Build Coastguard Worker  Scheduler State API support is required in your FreeRTOS Configuration, i.e.
21*61c4878aSAndroid Build Coastguard Worker  ``INCLUDE_xTaskGetSchedulerState == 1``.
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard WorkerThis backend always permits users to start threads where static contexts are
24*61c4878aSAndroid Build Coastguard Workerpassed in as an option. As a quick example, a detached thread can be created as
25*61c4878aSAndroid Build Coastguard Workerfollows:
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard Worker   #include "FreeRTOS.h"
30*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/detached_thread.h"
31*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/config.h"
32*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/context.h"
33*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/options.h"
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker   constexpr UBaseType_t kFooPriority =
36*61c4878aSAndroid Build Coastguard Worker       pw::thread::freertos::config::kDefaultPriority;
37*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kFooStackSizeWords =
38*61c4878aSAndroid Build Coastguard Worker       pw::thread::freertos::config::kDefaultStackSizeWords;
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker   pw::thread::freertos::StaticContextWithStack<kFooStackSizeWords>
41*61c4878aSAndroid Build Coastguard Worker       example_thread_context;
42*61c4878aSAndroid Build Coastguard Worker   void StartExampleThread() {
43*61c4878aSAndroid Build Coastguard Worker     pw::thread::DetachedThread(
44*61c4878aSAndroid Build Coastguard Worker         pw::thread::freertos::Options()
45*61c4878aSAndroid Build Coastguard Worker             .set_name("static_example_thread")
46*61c4878aSAndroid Build Coastguard Worker             .set_priority(kFooPriority)
47*61c4878aSAndroid Build Coastguard Worker             .set_static_context(example_thread_context),
48*61c4878aSAndroid Build Coastguard Worker         example_thread_function);
49*61c4878aSAndroid Build Coastguard Worker   }
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard WorkerAlternatively when ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is
52*61c4878aSAndroid Build Coastguard Workerenabled, dynamic thread allocation can be used. The above example could instead
53*61c4878aSAndroid Build Coastguard Workerbe done as follows:
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker   #include "FreeRTOS.h"
58*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/detached_thread.h"
59*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/config.h"
60*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/context.h"
61*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_freertos/options.h"
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker   constexpr UBaseType_t kFooPriority =
64*61c4878aSAndroid Build Coastguard Worker       pw::thread::freertos::config::kDefaultPriority;
65*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kFooStackSizeWords =
66*61c4878aSAndroid Build Coastguard Worker       pw::thread::freertos::config::kDefaultStackSizeWords;
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker   void StartExampleThread() {
69*61c4878aSAndroid Build Coastguard Worker     pw::thread::DetachedThread(
70*61c4878aSAndroid Build Coastguard Worker         pw::thread::freertos::Options()
71*61c4878aSAndroid Build Coastguard Worker             .set_name("dyanmic_example_thread")
72*61c4878aSAndroid Build Coastguard Worker             .set_priority(kFooPriority)
73*61c4878aSAndroid Build Coastguard Worker             .set_stack_size(kFooStackSizeWords),
74*61c4878aSAndroid Build Coastguard Worker         example_thread_function)
75*61c4878aSAndroid Build Coastguard Worker   }
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard WorkerModule Configuration Options
79*61c4878aSAndroid Build Coastguard Worker============================
80*61c4878aSAndroid Build Coastguard WorkerThe following configurations can be adjusted via compile-time configuration of
81*61c4878aSAndroid Build Coastguard Workerthis module, see the
82*61c4878aSAndroid Build Coastguard Worker:ref:`module documentation <module-structure-compile-time-configuration>` for
83*61c4878aSAndroid Build Coastguard Workermore details.
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_JOINING_ENABLED
86*61c4878aSAndroid Build Coastguard Worker
87*61c4878aSAndroid Build Coastguard Worker  Whether thread joining is enabled. By default this is disabled.
88*61c4878aSAndroid Build Coastguard Worker
89*61c4878aSAndroid Build Coastguard Worker  We suggest only enabling this when thread joining is required to minimize
90*61c4878aSAndroid Build Coastguard Worker  the RAM and ROM cost of threads.
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker  Enabling this grows the RAM footprint of every ``pw::Thread`` as it adds a
93*61c4878aSAndroid Build Coastguard Worker  ``StaticEventGroup_t`` to every thread's ``pw::thread::freertos::Context``. In
94*61c4878aSAndroid Build Coastguard Worker  addition, there is a minute ROM cost to construct and destroy this added
95*61c4878aSAndroid Build Coastguard Worker  object.
96*61c4878aSAndroid Build Coastguard Worker
97*61c4878aSAndroid Build Coastguard Worker  ``PW_THREAD_JOINING_ENABLED`` gets set to this value.
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker  Whether dynamic allocation for threads (stacks and contexts) is enabled. By
102*61c4878aSAndroid Build Coastguard Worker  default this matches the FreeRTOS configuration on whether dynamic
103*61c4878aSAndroid Build Coastguard Worker  allocations are enabled. Note that static contexts **must** be provided if
104*61c4878aSAndroid Build Coastguard Worker  dynamic allocations are disabled.
105*61c4878aSAndroid Build Coastguard Worker
106*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_STACK_SIZE_WORDS
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard Worker   The default stack size in words. By default this uses the minimal FreeRTOS
109*61c4878aSAndroid Build Coastguard Worker   stack size based on ``configMINIMAL_STACK_SIZE``.
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_PRIORITY
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker   The default thread priority. By default this uses the minimal FreeRTOS
114*61c4878aSAndroid Build Coastguard Worker   priority level above the idle priority (``tskIDLE_PRIORITY + 1``).
115*61c4878aSAndroid Build Coastguard Worker
116*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_MAXIMUM_PRIORITY
117*61c4878aSAndroid Build Coastguard Worker
118*61c4878aSAndroid Build Coastguard Worker  The maximum thread priority. By default this uses the value below the
119*61c4878aSAndroid Build Coastguard Worker  number of priorities defined by the FreeRTOS configuration
120*61c4878aSAndroid Build Coastguard Worker  (``configMAX_PRIORITIES - 1``).
121*61c4878aSAndroid Build Coastguard Worker
122*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_FREERTOS_CONFIG_LOG_LEVEL
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard Worker  The log level to use for this module. Logs below this level are omitted.
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard WorkerFreeRTOS Thread Options
127*61c4878aSAndroid Build Coastguard Worker=======================
128*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: pw::thread::freertos::Options
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_name(const char* name)
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard Worker    Sets the name for the FreeRTOS task, note that this will be truncated
133*61c4878aSAndroid Build Coastguard Worker    based on ``configMAX_TASK_NAME_LEN``. This is deep copied by FreeRTOS into
134*61c4878aSAndroid Build Coastguard Worker    the task's task control block (TCB).
135*61c4878aSAndroid Build Coastguard Worker
136*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_priority(UBaseType_t priority)
137*61c4878aSAndroid Build Coastguard Worker
138*61c4878aSAndroid Build Coastguard Worker    Sets the priority for the FreeRTOS task. This must be a value between
139*61c4878aSAndroid Build Coastguard Worker    ``0`` to ``PW_THREAD_FREERTOS_CONFIG_MAXIMUM_PRIORITY``. Higher priority
140*61c4878aSAndroid Build Coastguard Worker    values have a higher priority.
141*61c4878aSAndroid Build Coastguard Worker
142*61c4878aSAndroid Build Coastguard Worker    Note that the idle task priority, ``tskIDLE_PRIORITY``, is fixed to ``0``.
143*61c4878aSAndroid Build Coastguard Worker    See the `FreeRTOS documentation on the idle task
144*61c4878aSAndroid Build Coastguard Worker    <https://www.freertos.org/RTOS-idle-task.html>`_ for more details.
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard Worker    Precondition: This must be <= PW_THREAD_FREERTOS_CONFIG_MAXIMUM_PRIORITY.
147*61c4878aSAndroid Build Coastguard Worker
148*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_stack_size(size_t size_words)
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker    Set the stack size in words for a dynamically thread.
151*61c4878aSAndroid Build Coastguard Worker
152*61c4878aSAndroid Build Coastguard Worker    This is only available if
153*61c4878aSAndroid Build Coastguard Worker    ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is enabled.
154*61c4878aSAndroid Build Coastguard Worker
155*61c4878aSAndroid Build Coastguard Worker    Precondition: size_words must be >= ``configMINIMAL_STACK_SIZE``
156*61c4878aSAndroid Build Coastguard Worker
157*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_static_context(pw::thread::freertos::Context& context)
158*61c4878aSAndroid Build Coastguard Worker
159*61c4878aSAndroid Build Coastguard Worker    Set the pre-allocated context (all memory needed to run a thread). The
160*61c4878aSAndroid Build Coastguard Worker    ``StaticContext`` can either be constructed with an externally provided
161*61c4878aSAndroid Build Coastguard Worker    ``pw::span<StackType_t>`` stack or the templated form of
162*61c4878aSAndroid Build Coastguard Worker    ``StaticContextWithStack<kStackSizeWords>`` can be used.
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker
165*61c4878aSAndroid Build Coastguard Worker-----------------------------
166*61c4878aSAndroid Build Coastguard WorkerThread Identification Backend
167*61c4878aSAndroid Build Coastguard Worker-----------------------------
168*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::Thread::id`` and ``pw::thread::get_id()`` is offered using
169*61c4878aSAndroid Build Coastguard Worker``xTaskGetCurrentTaskHandle()``. It uses ``DASSERT`` to ensure that it is not
170*61c4878aSAndroid Build Coastguard Workerinvoked from interrupt context and if possible that the scheduler has started
171*61c4878aSAndroid Build Coastguard Workervia ``xTaskGetSchedulerState()``.
172*61c4878aSAndroid Build Coastguard Worker
173*61c4878aSAndroid Build Coastguard Worker------------------------
174*61c4878aSAndroid Build Coastguard WorkerThread Iteration Backend
175*61c4878aSAndroid Build Coastguard Worker------------------------
176*61c4878aSAndroid Build Coastguard Worker``pw_thread_freertos_TSKTCB_BACKEND`` to be configured
177*61c4878aSAndroid Build Coastguard Workerproperly and ``pw_third_party_freertos_DISABLE_TASKS_STATICS`` to be enabled.
178*61c4878aSAndroid Build Coastguard WorkerTo allow for peak stack usage measurement, the FreeRTOS config
179*61c4878aSAndroid Build Coastguard Worker``INCLUDE_uxTaskGetStackHighWaterMark`` should also be enabled.
180*61c4878aSAndroid Build Coastguard Worker
181*61c4878aSAndroid Build Coastguard Worker--------------------
182*61c4878aSAndroid Build Coastguard WorkerThread Sleep Backend
183*61c4878aSAndroid Build Coastguard Worker--------------------
184*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::thread::sleep_for()`` and ``pw::thread::sleep_until()`` is
185*61c4878aSAndroid Build Coastguard Workerofferred using ``vTaskDelay()`` if the duration is at least one tick, else
186*61c4878aSAndroid Build Coastguard Worker``taskYIELD()`` is used. It uses ``pw::this_thread::get_id() != Thread::id()``
187*61c4878aSAndroid Build Coastguard Workerto ensure it invoked only from a thread.
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard Worker--------------------
190*61c4878aSAndroid Build Coastguard WorkerThread Yield Backend
191*61c4878aSAndroid Build Coastguard Worker--------------------
192*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::thread::yield()`` is offered using via ``taskYIELD()``.
193*61c4878aSAndroid Build Coastguard WorkerIt uses ``pw::this_thread::get_id() != Thread::id()`` to ensure it invoked only
194*61c4878aSAndroid Build Coastguard Workerfrom a thread.
195*61c4878aSAndroid Build Coastguard Worker
196*61c4878aSAndroid Build Coastguard Worker---------------------------
197*61c4878aSAndroid Build Coastguard WorkerTest Thread Context Backend
198*61c4878aSAndroid Build Coastguard Worker---------------------------
199*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::thread::TestThreadContext()`` is offered using default
200*61c4878aSAndroid Build Coastguard Workeroptions and a static stack size of 8192 words.
201*61c4878aSAndroid Build Coastguard Worker
202*61c4878aSAndroid Build Coastguard Worker---------
203*61c4878aSAndroid Build Coastguard WorkerUtilities
204*61c4878aSAndroid Build Coastguard Worker---------
205*61c4878aSAndroid Build Coastguard Worker``ForEachThread()``
206*61c4878aSAndroid Build Coastguard Worker===================
207*61c4878aSAndroid Build Coastguard WorkerIn cases where an operation must be performed for every thread,
208*61c4878aSAndroid Build Coastguard Worker``ForEachThread()`` can be used to iterate over all the created thread TCBs.
209*61c4878aSAndroid Build Coastguard WorkerNote that it's only safe to use this while the scheduler and interrupts are
210*61c4878aSAndroid Build Coastguard Workerdisabled.
211*61c4878aSAndroid Build Coastguard Worker
212*61c4878aSAndroid Build Coastguard WorkerCalling this before the scheduler has started, via ``vTaskStartScheduler()``, is
213*61c4878aSAndroid Build Coastguard Workernon-fatal but will result in no action and a ``FailedPrecondition`` error code.
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard WorkerAn ``Aborted`` error status is returned if the provided callback returns
216*61c4878aSAndroid Build Coastguard Worker``false`` to request an early termination of thread iteration.
217*61c4878aSAndroid Build Coastguard Worker
218*61c4878aSAndroid Build Coastguard Worker*Return values*
219*61c4878aSAndroid Build Coastguard Worker
220*61c4878aSAndroid Build Coastguard Worker* ``FailedPrecondition``: Returned when ``ForEachThread()`` is run before the OS
221*61c4878aSAndroid Build Coastguard Worker  has been initialized.
222*61c4878aSAndroid Build Coastguard Worker* ``Aborted``: The callback requested an early-termination of thread iteration.
223*61c4878aSAndroid Build Coastguard Worker* ``OkStatus``: The callback has been successfully run with every thread.
224*61c4878aSAndroid Build Coastguard Worker
225*61c4878aSAndroid Build Coastguard Worker.. Note:: This uses an unsupported method to iterate the threads in a more
226*61c4878aSAndroid Build Coastguard Worker   efficient manner while also supporting interrupt contexts. This requires
227*61c4878aSAndroid Build Coastguard Worker   linking against internal statics from the FreeRTOS kernel,
228*61c4878aSAndroid Build Coastguard Worker   :ref:`pw_third_party_freertos_DISABLE_TASKS_STATICS <third_party-freertos_disable_task_statics>`
229*61c4878aSAndroid Build Coastguard Worker   must be used.
230*61c4878aSAndroid Build Coastguard Worker
231*61c4878aSAndroid Build Coastguard Worker--------------------
232*61c4878aSAndroid Build Coastguard WorkerSnapshot integration
233*61c4878aSAndroid Build Coastguard Worker--------------------
234*61c4878aSAndroid Build Coastguard WorkerThis ``pw_thread`` backend provides helper functions that capture FreeRTOS
235*61c4878aSAndroid Build Coastguard Workerthread state to a ``pw::Thread`` proto.
236*61c4878aSAndroid Build Coastguard Worker
237*61c4878aSAndroid Build Coastguard WorkerFreeRTOS tskTCB facade
238*61c4878aSAndroid Build Coastguard Worker======================
239*61c4878aSAndroid Build Coastguard WorkerUnfortunately FreeRTOS entirely hides the contents of the TCB inside of
240*61c4878aSAndroid Build Coastguard Worker``Source/tasks.c``, but it's necessary for snapshot processing in order to
241*61c4878aSAndroid Build Coastguard Workeraccess the stack limits from interrupt contexts. For this reason, FreeRTOS
242*61c4878aSAndroid Build Coastguard Workersnapshot integration relies on the ``pw_thread_freertos:freertos_tsktcb`` facade
243*61c4878aSAndroid Build Coastguard Workerto provide the ``tskTCB`` definition. By default, a header will automatically be
244*61c4878aSAndroid Build Coastguard Workergenerated from FreeRTOS's ``tasks.c`` file to work around this limitation.
245*61c4878aSAndroid Build Coastguard Worker
246*61c4878aSAndroid Build Coastguard WorkerIn the event that the automatic header generation is incompatible with your
247*61c4878aSAndroid Build Coastguard Workerversion of FreeRTOS, ``pw_thread_freertos_FREERTOS_TSKTCB_BACKEND`` must be
248*61c4878aSAndroid Build Coastguard Workerconfigured to point to a source set that provides the ``struct tskTCB``
249*61c4878aSAndroid Build Coastguard Workerdefinition through ``pw_thread_freertos_backend/freertos_tsktcb.h``. The facade
250*61c4878aSAndroid Build Coastguard Workerasserts that this definition matches the size of FreeRTOS's ``StaticTask_T``
251*61c4878aSAndroid Build Coastguard Workerwhich is the public opaque TCB type.
252*61c4878aSAndroid Build Coastguard Worker
253*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()``
254*61c4878aSAndroid Build Coastguard Worker=====================
255*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()`` captures the thread name, state, and stack information for
256*61c4878aSAndroid Build Coastguard Workerthe provided TCB to a ``pw::Thread`` protobuf encoder. To ensure the most
257*61c4878aSAndroid Build Coastguard Workerup-to-date information is captured, the stack pointer for the currently running
258*61c4878aSAndroid Build Coastguard Workerthread must be provided for cases where the running thread is being captured.
259*61c4878aSAndroid Build Coastguard WorkerFor ARM Cortex-M CPUs, you can do something like this:
260*61c4878aSAndroid Build Coastguard Worker
261*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
262*61c4878aSAndroid Build Coastguard Worker
263*61c4878aSAndroid Build Coastguard Worker   // Capture PSP.
264*61c4878aSAndroid Build Coastguard Worker   void* stack_ptr = 0;
265*61c4878aSAndroid Build Coastguard Worker   asm volatile("mrs %0, psp\n" : "=r"(stack_ptr));
266*61c4878aSAndroid Build Coastguard Worker   pw::thread::ProcessThreadStackCallback cb =
267*61c4878aSAndroid Build Coastguard Worker       [](pw::thread::proto::Thread::StreamEncoder& encoder,
268*61c4878aSAndroid Build Coastguard Worker          pw::ConstByteSpan stack) -> pw::Status {
269*61c4878aSAndroid Build Coastguard Worker     return encoder.WriteRawStack(stack);
270*61c4878aSAndroid Build Coastguard Worker   };
271*61c4878aSAndroid Build Coastguard Worker   pw::thread::threadx::SnapshotThread(my_thread, thread_state, stack_ptr,
272*61c4878aSAndroid Build Coastguard Worker                                       snapshot_encoder, cb);
273*61c4878aSAndroid Build Coastguard Worker
274*61c4878aSAndroid Build Coastguard WorkerSome FreeRTOS ports (e.g. RISC-V) automatically store the stack pointer back
275*61c4878aSAndroid Build Coastguard Workerinto the running thread's TCB upon exception entry, so there's no need to inject
276*61c4878aSAndroid Build Coastguard Workeran updated stack pointer. If you're unsure of your platform's behavior, inject
277*61c4878aSAndroid Build Coastguard Workeran updated stack pointer captured upon exception entry to be safe.
278*61c4878aSAndroid Build Coastguard Worker
279*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()`` wraps the singular thread capture to instead captures
280*61c4878aSAndroid Build Coastguard Workerall created threads to a ``pw::thread::proto::SnapshotThreadInfo`` message
281*61c4878aSAndroid Build Coastguard Workerwhich also captures the thread state for you. This proto
282*61c4878aSAndroid Build Coastguard Workermessage overlays a snapshot, so it is safe to static cast a
283*61c4878aSAndroid Build Coastguard Worker``pw::snapshot::Snapshot::StreamEncoder`` to a
284*61c4878aSAndroid Build Coastguard Worker``pw::thread::proto::SnapshotThreadInfo::StreamEncoder`` when calling this
285*61c4878aSAndroid Build Coastguard Workerfunction.
286*61c4878aSAndroid Build Coastguard Worker
287*61c4878aSAndroid Build Coastguard Worker.. Note:: ``SnapshotThreads()`` is only safe to use this while the scheduler and
288*61c4878aSAndroid Build Coastguard Worker   interrupts are disabled as it relies on ``ForEachThread()``.
289*61c4878aSAndroid Build Coastguard Worker
290*61c4878aSAndroid Build Coastguard WorkerThread Stack Capture
291*61c4878aSAndroid Build Coastguard Worker--------------------
292*61c4878aSAndroid Build Coastguard WorkerSnapshot attempts to capture as much of the thread stack state as possible,
293*61c4878aSAndroid Build Coastguard Workerhowever it can be limited by the FreeRTOS configuration.
294*61c4878aSAndroid Build Coastguard Worker
295*61c4878aSAndroid Build Coastguard WorkerThe ``stack_start_ptr`` can only be provided if the ``portSTACK_GROWTH`` is < 0,
296*61c4878aSAndroid Build Coastguard Workeri.e. the stack grows down, when ``configRECORD_STACK_HIGH_ADDRESS`` is enabled.
297*61c4878aSAndroid Build Coastguard Worker
298*61c4878aSAndroid Build Coastguard WorkerThe ``stack_pointer_est_peak`` can only be provided when
299*61c4878aSAndroid Build Coastguard Worker``config_USE_TRACE_FACILITY`` and/or ``INCLUDE_uxTaskGetStackHighWaterMark`` are
300*61c4878aSAndroid Build Coastguard Workerenabled and ``stack_start_ptr``'s requirements above are met.
301