Description
Origin
Pigweed
https://pigweed.dev/
https://pigweed.googlesource.com/pigweed/pigweed
Purpose
Pigweed is a collection of embedded specific utilities that aim at making embedded application development easier/faster.
Mode of integration
I would like this to be integrated as a module. Pigweed is highly complimentary to Zephyr and provides many great utilities for our developers. It should help reduce the overhead of new projects as well as offload some feature (mainly subsystem features) by leveraging what other teams are building. I would suggest putting this in github.com/zephyrproject-rtos/pigweed
Maintainership
Maintainers:
Collaborators:
Pull Request
License
Apache 2.0
Introduction
This RFC proposes adding Pigweed as a Zephyr module to provide developers a path to using C++ as the primary language in their Zephyr projects, and to provide Zephyr with a path to general C++ support.
Pigweed is an open source project that aims to make embedded software development more efficient, robust, and enjoyable. Pigweed's collection of libraries (known as modules in the Pigweed docs) are designed to enable modern C++ best practices in embedded projects without compromising performance, safety, or size. Pigweed achieves this through modularity, allowing projects to use only the modules they need without taking on additional, unused dependencies.
The core Pigweed team is staffed by Google, but the codebase (GitHub mirror) is open source and welcomes external contributions. Pigweed is shipping in numerous Google hardware products, and is also used widely outside of Google:
- In the Matter standard used across the IoT industry
- Drones used by Zipline
- Satellites launched by Binar
Problem description
Zephyr adoption could be improved by robust C++ support
"As of 2019, 25% of embedded development occurs in C++, and that share is growing" according to the 2019 Embedded Markets Study by EETimes and embedded.com. It is particularly common in cutting-edge projects such as robotics, drones, and machine learning.
One common motivation for using C++ rather than C is that C++ interfaces are more ergonomic and less error prone than their C counterparts. For example, Pigweed mutexes can be used with std::lock_guard, which ensures a mutex is released before leaving a function. Furthermore, they are compatible with Clang's thread safety annotations, which catch synchronization bugs during compilation.
Language Features, C++ Roadmap #45785, and C++ support in Zephyr #31281 give the impression that Zephyr only has basic C++ support, therefore embedded teams with a requirement to use C++ are unlikely to consider Zephyr as a viable first choice. The following issues are examples of Zephyr developers having trouble writing Zephyr projects in C++ or evolving Zephyr itself due to C++ support limitations:
- Bluetooth API does not support C++ projects #59405
- address-of-temporary idiom not allowed in C++ #18551
- Bluetooth Module for CPP #55433
- C++ std::async and std::future support #31559
- Current view on use of C++ for Kernel/Driver development #52991
- C++ compilation succeess, while warning bits/c++config.h not found. #55931
Roadblocks to threading and synchronization support due to inflexible C++ toolchain issues
The implementation proposed in C++ Roadmap #45785 will not work with Clang. The roadmap proposes implementing gthr-posix.h from libstdc++ to support the standard library for threading and synchronization, such as std::thread and std::mutex. This requires integration with GCC’s libstdc++ and is not portable to other toolchains or standard library implementations.
Other examples of C++ toolchain issues:
- Build excludes paths to standard C++ headers when using GNUARMEMB toolchain variant #36823
- Toolchain C++ headers can be included when libstdc++ is not selected #36644
- Build fails for native_posix board when using C++ header #40023
Missing C++ coding guidelines
Establish C++ coding guidelines #45195 indicates that Zephyr is looking for a way to establish and enforce a C++ style guide.
In summary, developers who want to use C++ and Zephyr are growing in number but lack the resources that make developing with C and Zephyr so effective.
Proposed changes
This RFC proposes to add Pigweed as a Zephyr module.
Enable robust C++ support in Zephyr through Pigweed interfaces
Pigweed provides C++ interfaces for RTOS primitives including threads, synchronization, time, and basic I/O. Developers using Pigweed and Zephyr can write software against those interfaces and use Zephyr’s implementations of those primitives:
- pw_thread: thread creation and execution that wraps the Zephyr threading API.
- pw_sync: synchronization primitives such as mutexes, semaphores, spin locks, etc.
- pw_chrono: time-related use cases similar to what std::chrono provides.
Pigweed has robust C++ testing support:
- pw_unit_test: a port of GoogleTest which enables leveraging of class structures and inheritance. As of #58046, these can be run by Twister directly.
Pigweed provides efficient embedded-friendly features that can be used instead of Standard Library classes:
- pw_span: similar to std::span in C++20, but compatible with C++14 and C++17.
- pw_containers: embedded system-friendly container classes such as vectors, queues, deques, lists, and related algorithms.
- pw_string: STL-like strings, but memory safe and efficient for embedded systems.
- pw_result and pw_status: modern status classes, equivalent to those in Abseil.
- pw_stream: a foundational interfacing for streaming data.
And many more. See Module guides for the full list.
Using these features doesn’t require any significant deviation from typical Zephyr development practices and you only need to include what you use. This is thanks to Pigweed’s modular architecture and the work that the ChromeOS and CHRE teams have done to integrate Pigweed with Zephyr.
Enable threading and synchronization support through the pw namespace
Rather than requiring toolchain-specific integration for threading and synchronization, Pigweed provides API-compatible versions of the standard library classes in the pw namespace. Pigweed’s classes work the same as the standard library versions, but can be used anywhere without toolchain integration. And if the toolchain’s threading and synchronization features are supported, the pw classes become trivial wrappers around the standard library classes with Pigweed’s facade pattern.
Zephyr could offer Pigweed’s efficient C++ threading and synchronization abstractions today via industry-standard interfaces. If Zephyr-native support for classes like std::thread and std::mutex is implemented in the future, these will integrate seamlessly with Pigweed’s classes.
Adopt Pigweed's C++ coding guidelines
Pigweed has a C++ style guide and Embedded C++ guide that could serve as the basis of Zephyr's C++ coding guidelines. The core Pigweed team will collaborate with the Zephyr team and Zephyr developers to evolve and expand the guides as new topics come up. Pigweed’s pw_presubmit module can be used to enforce the coding guidelines and code quality.
The Pigweed team has invested significant effort in creating embedded C++ best practices and testing them in practice. Zephyr can inherit that investment!