xref: /aosp_15_r20/external/pigweed/pw_thread_embos/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_thread_embos:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker===============
4*61c4878aSAndroid Build Coastguard Workerpw_thread_embos
5*61c4878aSAndroid Build Coastguard Worker===============
6*61c4878aSAndroid Build Coastguard WorkerThis is a set of backends for pw_thread based on embOS v4.
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 or ``pw::Thread`` is offered using ``OS_CreateTaskEx()``. Optional
15*61c4878aSAndroid Build Coastguard Workerjoining support is enabled via an ``OS_EVENT`` in each thread's context.
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard WorkerThis backend permits users to start threads where contexts must be explicitly
18*61c4878aSAndroid Build Coastguard Workerallocated and passed in as an option. As a quick example, a detached thread
19*61c4878aSAndroid Build Coastguard Workercan be created as follows:
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/detached_thread.h"
24*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_embos/config.h"
25*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_embos/context.h"
26*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_embos/options.h"
27*61c4878aSAndroid Build Coastguard Worker   #include "RTOS.h"  // For the embOS types.
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard Worker   constexpr OS_PRIO kFooPriority =
30*61c4878aSAndroid Build Coastguard Worker       pw::thread::embos::config::kDefaultPriority;
31*61c4878aSAndroid Build Coastguard Worker   constexpr OS_UINT kFooTimeSliceInterval =
32*61c4878aSAndroid Build Coastguard Worker       pw::thread::embos::config::kDefaultTimeSliceInterval;
33*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kFooStackSizeWords =
34*61c4878aSAndroid Build Coastguard Worker       pw::thread::embos::config::kDefaultStackSizeWords;
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker   pw::thread::embos::ContextWithStack<kFooStackSizeWords>
37*61c4878aSAndroid Build Coastguard Worker       example_thread_context;
38*61c4878aSAndroid Build Coastguard Worker   void StartExampleThread() {
39*61c4878aSAndroid Build Coastguard Worker     pw::thread::DetachedThread(
40*61c4878aSAndroid Build Coastguard Worker         pw::thread::embos::Options()
41*61c4878aSAndroid Build Coastguard Worker             .set_name("example_thread")
42*61c4878aSAndroid Build Coastguard Worker             .set_priority(kFooPriority)
43*61c4878aSAndroid Build Coastguard Worker             .set_time_slice_interval(kFooTimeSliceInterval)
44*61c4878aSAndroid Build Coastguard Worker             .set_context(example_thread_context),
45*61c4878aSAndroid Build Coastguard Worker         example_thread_function);
46*61c4878aSAndroid Build Coastguard Worker   }
47*61c4878aSAndroid Build Coastguard Worker
48*61c4878aSAndroid Build Coastguard Worker
49*61c4878aSAndroid Build Coastguard WorkerModule Configuration Options
50*61c4878aSAndroid Build Coastguard Worker============================
51*61c4878aSAndroid Build Coastguard WorkerThe following configurations can be adjusted via compile-time configuration of
52*61c4878aSAndroid Build Coastguard Workerthis module, see the
53*61c4878aSAndroid Build Coastguard Worker:ref:`module documentation <module-structure-compile-time-configuration>` for
54*61c4878aSAndroid Build Coastguard Workermore details.
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_JOINING_ENABLED
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard Worker  Whether thread joining is enabled. By default this is disabled.
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard Worker  We suggest only enabling this when thread joining is required to minimize
61*61c4878aSAndroid Build Coastguard Worker  the RAM and ROM cost of threads.
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker  Enabling this grows the RAM footprint of every pw::Thread as it adds an
64*61c4878aSAndroid Build Coastguard Worker  OS_EVENT to every thread's pw::thread::embos::Context. In addition, there is a
65*61c4878aSAndroid Build Coastguard Worker  minute ROM cost to construct and destroy this added object.
66*61c4878aSAndroid Build Coastguard Worker
67*61c4878aSAndroid Build Coastguard Worker  PW_THREAD_JOINING_ENABLED gets set to this value.
68*61c4878aSAndroid Build Coastguard Worker
69*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_MINIMUM_STACK_SIZE_WORDS
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker  The minimum stack size in words. By default this uses Segger's recommendation
72*61c4878aSAndroid Build Coastguard Worker  of 68 bytes.
73*61c4878aSAndroid Build Coastguard Worker
74*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_DEFAULT_STACK_SIZE_WORDS
75*61c4878aSAndroid Build Coastguard Worker
76*61c4878aSAndroid Build Coastguard Worker  The default stack size in words. By default this uses Segger's recommendation
77*61c4878aSAndroid Build Coastguard Worker  of 256 bytes to start.
78*61c4878aSAndroid Build Coastguard Worker
79*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_MAX_THREAD_NAME_LEN
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker  The maximum length of a thread's name, not including null termination. By
82*61c4878aSAndroid Build Coastguard Worker  default this is arbitrarily set to 15. This results in an array of characters
83*61c4878aSAndroid Build Coastguard Worker  which is this length + 1 bytes in every ``pw::Thread``'s context.
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_MIN_PRIORITY
86*61c4878aSAndroid Build Coastguard Worker
87*61c4878aSAndroid Build Coastguard Worker  The minimum priority level, this is normally 1, since 0 is not a valid
88*61c4878aSAndroid Build Coastguard Worker  priority level.
89*61c4878aSAndroid Build Coastguard Worker
90*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_DEFAULT_PRIORITY
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker  The default priority level. By default this uses the minimal embOS priority.
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_DEFAULT_TIME_SLICE_INTERVAL
95*61c4878aSAndroid Build Coastguard Worker
96*61c4878aSAndroid Build Coastguard Worker  The round robin time slice tick interval for threads at the same priority.
97*61c4878aSAndroid Build Coastguard Worker  By default this is set to 2 ticks based on the embOS default.
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker.. c:macro:: PW_THREAD_EMBOS_CONFIG_LOG_LEVEL
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker  The log level to use for this module. Logs below this level are omitted.
102*61c4878aSAndroid Build Coastguard Worker
103*61c4878aSAndroid Build Coastguard WorkerembOS Thread Options
104*61c4878aSAndroid Build Coastguard Worker====================
105*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: pw::thread::embos::Options
106*61c4878aSAndroid Build Coastguard Worker
107*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_name(const char* name)
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard Worker    Sets the name for the embOS task, this is optional.
110*61c4878aSAndroid Build Coastguard Worker    Note that this will be deep copied into the context and may be truncated
111*61c4878aSAndroid Build Coastguard Worker    based on ``PW_THREAD_EMBOS_CONFIG_MAX_THREAD_NAME_LEN``.
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_priority(OS_PRIO priority)
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker    Sets the priority for the embOS task. Higher values are higher priority,
116*61c4878aSAndroid Build Coastguard Worker    see embOS OS_CreateTaskEx for more detail.
117*61c4878aSAndroid Build Coastguard Worker    Precondition: This must be >= ``PW_THREAD_EMBOS_CONFIG_MIN_PRIORITY``.
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_time_slice_interval(OS_UINT time_slice_interval)
120*61c4878aSAndroid Build Coastguard Worker
121*61c4878aSAndroid Build Coastguard Worker    Sets the number of ticks this thread is allowed to run before other ready
122*61c4878aSAndroid Build Coastguard Worker    threads of the same priority are given a chance to run.
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard Worker    A value of 0 disables time-slicing of this thread.
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard Worker    Precondition: This must be <= 255 ticks.
127*61c4878aSAndroid Build Coastguard Worker
128*61c4878aSAndroid Build Coastguard Worker  .. cpp:function:: set_context(pw::thread::embos::Context& context)
129*61c4878aSAndroid Build Coastguard Worker
130*61c4878aSAndroid Build Coastguard Worker    Set the pre-allocated context (all memory needed to run a thread). Note that
131*61c4878aSAndroid Build Coastguard Worker    this is required for this thread creation backend! The ``Context`` can
132*61c4878aSAndroid Build Coastguard Worker    either be constructed with an externally provided ``pw::span<OS_UINT>``
133*61c4878aSAndroid Build Coastguard Worker    stack or the templated form of ``ContextWithStack<kStackSizeWords>`` can
134*61c4878aSAndroid Build Coastguard Worker    be used.
135*61c4878aSAndroid Build Coastguard Worker
136*61c4878aSAndroid Build Coastguard Worker
137*61c4878aSAndroid Build Coastguard Worker-----------------------------
138*61c4878aSAndroid Build Coastguard WorkerThread Identification Backend
139*61c4878aSAndroid Build Coastguard Worker-----------------------------
140*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::Thread::id`` and ``pw::thread::get_id()`` is offerred using
141*61c4878aSAndroid Build Coastguard Worker``OS_GetTaskID()``. It uses ``DASSERT`` to ensure that the scheduler has started
142*61c4878aSAndroid Build Coastguard Workervia ``OS_IsRunning()``.
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard Worker--------------------
145*61c4878aSAndroid Build Coastguard WorkerThread Sleep Backend
146*61c4878aSAndroid Build Coastguard Worker--------------------
147*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::thread::sleep_for()`` and ``pw::thread::sleep_until()`` is
148*61c4878aSAndroid Build Coastguard Workerofferred using ``OS_Delay()`` if the duration is at least one tick, else
149*61c4878aSAndroid Build Coastguard Worker``OS_Yield()`` is used. It uses ``pw::this_thread::get_id() != Thread::id()`` to
150*61c4878aSAndroid Build Coastguard Workerensure it invoked only from a thread.
151*61c4878aSAndroid Build Coastguard Worker
152*61c4878aSAndroid Build Coastguard Worker--------------------
153*61c4878aSAndroid Build Coastguard WorkerThread Yield Backend
154*61c4878aSAndroid Build Coastguard Worker--------------------
155*61c4878aSAndroid Build Coastguard WorkerA backend for ``pw::thread::yield()`` is offered using via ``OS_Yield()``.
156*61c4878aSAndroid Build Coastguard WorkerIt uses ``pw::this_thread::get_id() != Thread::id()`` to ensure it invoked only
157*61c4878aSAndroid Build Coastguard Workerfrom a thread.
158*61c4878aSAndroid Build Coastguard Worker
159*61c4878aSAndroid Build Coastguard Worker---------
160*61c4878aSAndroid Build Coastguard WorkerUtilities
161*61c4878aSAndroid Build Coastguard Worker---------
162*61c4878aSAndroid Build Coastguard Worker``ForEachThread()``
163*61c4878aSAndroid Build Coastguard Worker===================
164*61c4878aSAndroid Build Coastguard WorkerIn cases where an operation must be performed for every thread,
165*61c4878aSAndroid Build Coastguard Worker``ForEachThread()`` can be used to iterate over all the created thread TCBs.
166*61c4878aSAndroid Build Coastguard WorkerNote that it's only safe to use this while the scheduler is suspended, and this
167*61c4878aSAndroid Build Coastguard Workershould only be used after ``OS_Start()`` has been called. Calling this before
168*61c4878aSAndroid Build Coastguard Workerthe scheduler has started is non-fatal, but will result in no action and a
169*61c4878aSAndroid Build Coastguard Worker``FailedPrecondition`` error code.
170*61c4878aSAndroid Build Coastguard Worker
171*61c4878aSAndroid Build Coastguard WorkerAn ``Aborted`` error status is returned if the provided callback returns
172*61c4878aSAndroid Build Coastguard Worker``false`` to request an early termination of thread iteration.
173*61c4878aSAndroid Build Coastguard Worker
174*61c4878aSAndroid Build Coastguard Worker*Return values*
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard Worker* ``FailedPrecondition``: Returned when ``ForEachThread()`` is run before the OS
177*61c4878aSAndroid Build Coastguard Worker  has been initialized.
178*61c4878aSAndroid Build Coastguard Worker* ``Aborted``: The callback requested an early-termination of thread iteration.
179*61c4878aSAndroid Build Coastguard Worker* ``OkStatus``: The callback has been successfully run with every thread.
180*61c4878aSAndroid Build Coastguard Worker
181*61c4878aSAndroid Build Coastguard Worker--------------------
182*61c4878aSAndroid Build Coastguard WorkerSnapshot Integration
183*61c4878aSAndroid Build Coastguard Worker--------------------
184*61c4878aSAndroid Build Coastguard WorkerThis ``pw_thread`` backend provides helper functions that capture embOS thread
185*61c4878aSAndroid Build Coastguard Workerinfo to a ``pw::Thread`` proto.
186*61c4878aSAndroid Build Coastguard Worker
187*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()``
188*61c4878aSAndroid Build Coastguard Worker=====================
189*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()`` captures the thread name, state, and stack information for
190*61c4878aSAndroid Build Coastguard Workerthe provided embOS TCB to a ``pw::Thread`` protobuf encoder. To ensure the most
191*61c4878aSAndroid Build Coastguard Workerup-to-date information is captured, the stack pointer for the currently running
192*61c4878aSAndroid Build Coastguard Workerthread must be provided for cases where the running thread is being captured.
193*61c4878aSAndroid Build Coastguard WorkerFor ARM Cortex-M CPUs, you can do something like this:
194*61c4878aSAndroid Build Coastguard Worker
195*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
196*61c4878aSAndroid Build Coastguard Worker
197*61c4878aSAndroid Build Coastguard Worker   // Capture PSP.
198*61c4878aSAndroid Build Coastguard Worker   void* stack_ptr = 0;
199*61c4878aSAndroid Build Coastguard Worker   asm volatile("mrs %0, psp\n" : "=r"(stack_ptr));
200*61c4878aSAndroid Build Coastguard Worker   pw::thread::ProcessThreadStackCallback cb =
201*61c4878aSAndroid Build Coastguard Worker       [](pw::thread::proto::Thread::StreamEncoder& encoder,
202*61c4878aSAndroid Build Coastguard Worker          pw::ConstByteSpan stack) -> pw::Status {
203*61c4878aSAndroid Build Coastguard Worker     return encoder.WriteRawStack(stack);
204*61c4878aSAndroid Build Coastguard Worker   };
205*61c4878aSAndroid Build Coastguard Worker   pw::thread::embos::SnapshotThread(my_thread, stack_ptr,
206*61c4878aSAndroid Build Coastguard Worker                                     snapshot_encoder, cb);
207*61c4878aSAndroid Build Coastguard Worker
208*61c4878aSAndroid Build Coastguard Worker``SnapshotThreads()`` wraps the singular thread capture to instead captures
209*61c4878aSAndroid Build Coastguard Workerall created threads to a ``pw::thread::proto::SnapshotThreadInfo`` message.
210*61c4878aSAndroid Build Coastguard WorkerThis proto message overlays a snapshot, so it is safe to static cast a
211*61c4878aSAndroid Build Coastguard Worker``pw::snapshot::Snapshot::StreamEncoder`` to a
212*61c4878aSAndroid Build Coastguard Worker``pw::thread::proto::SnapshotThreadInfo::StreamEncoder`` when calling this
213*61c4878aSAndroid Build Coastguard Workerfunction.
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard WorkerThread Name Capture
216*61c4878aSAndroid Build Coastguard Worker-------------------
217*61c4878aSAndroid Build Coastguard WorkerIn order to capture thread names when snapshotting a thread, embOS must have
218*61c4878aSAndroid Build Coastguard Worker``OS_TRACKNAME`` enabled. If ``OS_TRACKNAME`` is disabled, no thread name
219*61c4878aSAndroid Build Coastguard Workeris captured. Enabling this is strongly recommended for debugability.
220*61c4878aSAndroid Build Coastguard Worker
221*61c4878aSAndroid Build Coastguard WorkerThread State Capture
222*61c4878aSAndroid Build Coastguard Worker--------------------
223*61c4878aSAndroid Build Coastguard WorkerembOS thread state is not part of embOS's public API. Despite this, the
224*61c4878aSAndroid Build Coastguard Workersnapshot integration captures thread state based on information on how the
225*61c4878aSAndroid Build Coastguard Workerthread state is represented from
226*61c4878aSAndroid Build Coastguard Worker`Segger's public forum <https://forum.segger.com/index.php/Thread/6548-ABANDONED-Task-state-values/?postID=23963#post23963>`_.
227*61c4878aSAndroid Build Coastguard WorkerThis has been tested on embOS 4.22, and was initially
228*61c4878aSAndroid Build Coastguard Workerreported for embOS 5.06. The logic Pigweed uses to interpret thread state may
229*61c4878aSAndroid Build Coastguard Workerbe incorrect for other versions of embOS.
230*61c4878aSAndroid Build Coastguard Worker
231*61c4878aSAndroid Build Coastguard WorkerThread Stack Capture
232*61c4878aSAndroid Build Coastguard Worker--------------------
233*61c4878aSAndroid Build Coastguard WorkerFull thread stack information capture is dependent on embOS tracking the stack
234*61c4878aSAndroid Build Coastguard Workerbounds for each task. When either ``OS_SUPPORT_MPU`` or ``OS_CHECKSTACK`` are
235*61c4878aSAndroid Build Coastguard Workerenabled, stack bounds are tracked and the callback for thread stack dumping
236*61c4878aSAndroid Build Coastguard Workerwill be called. If both of these options are disabled, ``stack_start_pointer``
237*61c4878aSAndroid Build Coastguard Workerand ``stack_end_pointer`` will not be captured, and the
238*61c4878aSAndroid Build Coastguard Worker``ProcessThreadStackCallback`` will not be called.
239