pw_thread_freertos: update docs Change-Id: I41c4252f884bccd8323c49ae8ddccbee76cd2741 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/45500 Pigweed-Auto-Submit: Ewout van Bekkum <ewout@google.com> Reviewed-by: Ewout van Bekkum <ewout@google.com> Reviewed-by: Keir Mierle <keir@google.com> Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/pw_thread_freertos/docs.rst b/pw_thread_freertos/docs.rst index 6628718..6633d1e 100644 --- a/pw_thread_freertos/docs.rst +++ b/pw_thread_freertos/docs.rst
@@ -1,8 +1,157 @@ .. _module-pw_thread_freertos: ------------------- +================== pw_thread_freertos ------------------- -This is a set of backends for pw_thread based on FreeRTOS. It is not ready for -use, and is under construction. +================== +This is a set of backends for pw_thread based on FreeRTOS. +.. contents:: + :local: + :depth: 1 + +.. Warning:: + This module is still under construction, the API is not yet stable. + +----------------------- +Thread Creation Backend +----------------------- +A backend for ``pw::thread::Thread`` is offered using ``xTaskCreateStatic()``. +Optional dynamic allocation for threads is supported using ``xTaskCreate()``. +Optional joining support is enabled via an ``StaticEventGroup_t`` in each +thread's context. + +This backend always permits users to start threads where static contexts are +passed in as an option. As a quick example, a detached thread can be created as +follows: + +.. code-block:: cpp + + #include "FreeRTOS.h" + #include "pw_thread/detached_thread.h" + #include "pw_thread_freertos/context.h" + #include "pw_thread_freertos/options.h" + + pw::thread::freertos::StaticContextWithStack<42> example_thread_context; + void StartExampleThread() { + pw::thread::DetachedThread( + pw::thread::freertos::Options() + .set_name("static_example_thread") + .set_priority(kFooPriority) + .set_static_context(example_thread_context), + example_thread_function) + } + +Alternatively when ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is +enabled, dynamic thread allocation can be used. The above example could instead +be done as follows: + +.. code-block:: cpp + + #include "FreeRTOS.h" + #include "pw_thread/detached_thread.h" + #include "pw_thread_freertos/context.h" + #include "pw_thread_freertos/options.h" + + void StartExampleThread() { + pw::thread::DetachedThread( + pw::thread::freertos::Options() + .set_name("dyanmic_example_thread") + .set_priority(kFooPriority) + .set_stack_size(42), + example_thread_function) + } + + +Module Configuration Options +============================ +The following configurations can be adjusted via compile-time configuration of +this module, see the +:ref:`module documentation <module-structure-compile-time-configuration>` for +more details. + +.. c:macro:: PW_THREAD_FREERTOS_CONFIG_JOINING_ENABLED + + Whether thread joining is enabled. By default this is disabled. + + We suggest only enabling this when thread joining is required to minimize + the RAM and ROM cost of threads. + + Enabling this grows the RAM footprint of every ``pw::thread::Thread`` as it + adds a ``StaticEventGroup_t`` to every thread's + ``pw::thread::freertos::Context``. In addition, there is a minute ROM cost to + construct and destroy this added object. + + ``PW_THREAD_JOINING_ENABLED`` gets set to this value. + +.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED + + Whether dynamic allocation for threads (stacks and contexts) is enabled. By + default this matches the FreeRTOS configuration on whether dynamic + allocations are enabled. Note that static contexts **must** be provided if + dynamic allocations are disabled. + +.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_STACK_SIZE_WORDS + + The default stack size in words. By default this uses the minimal FreeRTOS + stack size based on ``configMINIMAL_STACK_SIZE``. + +.. c:macro:: PW_THREAD_FREERTOS_CONFIG_DEFAULT_PRIORITY + + The default stack size in words. By default this uses the minimal FreeRTOS + priority level above the idle priority (``tskIDLE_PRIORITY + 1``). + +FreeRTOS Thread Options +======================= +.. cpp:class:: pw::thread::freertos::Options + + .. cpp:function:: set_name(const char* name) + + Sets the name for the FreeRTOS task, note that this will be truncated + based on ``configMAX_TASK_NAME_LEN``. This is deep copied by FreeRTOS into + the task's task control block (TCB). + + .. cpp:function:: set_priority(UBaseType_t priority) + + Sets the priority for the FreeRTOS task. This must be a value between + ``tskIDLE_PRIORITY`` or ``0`` to ``configMAX_PRIORITIES - 1``. Higher + priority values have a higher priority. + + .. cpp:function:: set_stack_size(size_t size_words) + + Set the stack size in words for a dynamically thread. + + This is only available if + ``PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED`` is enabled. + + Precondition: size_words must be >= ``configMINIMAL_STACK_SIZE`` + + .. cpp:function:: set_static_context(pw::thread::freertos::Context& context) + + Set the pre-allocated context (all memory needed to run a thread). The + ``StaticContext`` can either be constructed with an externally provided + ``std::span<StackType_t>`` stack or the templated form of + ``StaticContextWithStack<kStackSizeWords>`` can be used. + + +----------------------------- +Thread Identification Backend +----------------------------- +A backend for ``pw::thread::Id`` and ``pw::thread::get_id()`` is offerred using +``xTaskGetCurrentTaskHandle()``. It uses ``DASSERT`` to ensure that it is not +invoked from interrupt context and if possible that the scheduler has started +via ``xTaskGetSchedulerState()``. + +-------------------- +Thread Sleep Backend +-------------------- +A backend for ``pw::thread::sleep_for()`` and ``pw::thread::sleep_until()`` is +offerred using ``vTaskDelay()`` if the duration is at least one tick, else +``taskYIELD()`` is used. It uses ``pw::this_thread::get_id() != thread::Id()`` +to ensure it invoked only from a thread. + +-------------------- +Thread Yield Backend +-------------------- +A backend for ``pw::thread::yield()`` is offered using via ``taskYIELD()``. +It uses ``pw::this_thread::get_id() != thread::Id()`` to ensure it invoked only +from a thread.
diff --git a/pw_thread_freertos/public/pw_thread_freertos/options.h b/pw_thread_freertos/public/pw_thread_freertos/options.h index 921faa4..7a70d12 100644 --- a/pw_thread_freertos/public/pw_thread_freertos/options.h +++ b/pw_thread_freertos/public/pw_thread_freertos/options.h
@@ -48,21 +48,24 @@ // Sets the name for the FreeRTOS task, note that this will be truncated // based on configMAX_TASK_NAME_LEN. + // This is deep copied by FreeRTOS into the task's task control block (TCB). constexpr Options set_name(const char* name) { name_ = name; return *this; } - // Sets the priority for the FreeRTOS task, see FreeRTOS xTaskCreate for more - // detail. + // Sets the priority for the FreeRTOS task. This must be a value between + // tskIDLE_PRIORITY or 0 to configMAX_PRIORITIES - 1. Higher priority values + // have a higher priority. constexpr Options set_priority(UBaseType_t priority) { priority_ = priority; return *this; } #if PW_THREAD_FREERTOS_CONFIG_DYNAMIC_ALLOCATION_ENABLED - // Set the stack size for dynamic thread allocations, see FreeRTOS xTaskCreate - // for more detail. + // Set the stack size of dynamic thread allocations. + // + // Precondition: size_words must be >= configMINIMAL_STACK_SIZE constexpr Options set_stack_size(size_t size_words) { PW_DASSERT(size_words >= config::kMinimumStackSizeWords); stack_size_words_ = size_words;