system/zbus: Port the Zephyr zbus message bus to NuttX - #3743
Open
JorgeGzm wants to merge 1 commit into
Open
Conversation
Port of the Zephyr RTOS zbus (many-to-many message bus with typed channels and decoupled observers), built entirely on native NuttX primitives and preserving the original declarative API (ZBUS_CHAN_DEFINE, ZBUS_LISTENER_DEFINE, ZBUS_SUBSCRIBER_DEFINE, ...). Features: listeners (synchronous callbacks), subscribers (queue of channel references), message subscribers (ordered message copies), async listeners (callback on the LP work queue), a deferred ISR-safe publisher (ZBUS_ISR_PUBLISHER_DEFINE/zbus_isr_pub), runtime observers, per-observation notification masks, observer enable/disable, message validators, channel user data, publish statistics, lookup by name/numeric id and channel/observer iteration. Mapping to NuttX primitives: - Channel/observer registration: link-time iterable sections (include/nuttx/iterable_sections.h, added to nuttx in a companion commit); notification masks live in .bss with their initial value preserved in ROM and applied on lazy init. - Channel lock: sem_t (enable CONFIG_PRIORITY_INHERITANCE instead of the Zephyr priority-boost/HLP). - Subscriber queues: kernel message queues (file_mq_*) opened lazily via pthread_once, usable from any task; mq payload copying replaces the Zephyr net_buf machinery entirely. - Async listeners: work_queue() on the LP work queue. - Timeouts: milliseconds with CLOCK_MONOTONIC deadlines (ZBUS_NO_WAIT/ZBUS_FOREVER). Includes a runnable example (examples/zbus, CONFIG_EXAMPLES_ZBUS) and a cmocka test suite (testing/zbus, CONFIG_TESTING_ZBUS) covering the full API: 16/16 tests passing on linum-stm32h753bi hardware, including multi-channel index grouping, mask semantics, runtime observer error paths, queue overflow/timeout semantics, async listener bursts and bit-exact float/double payload delivery across every observer type (sensor-style messages with a float-math validator). Requirements: FLAT build; CONFIG_MQ_MAXMSGSIZE >= pointer size + CONFIG_ZBUS_MSG_SUBSCRIBER_MAX_MSG_SIZE for message subscribers; board linker script including <nuttx/linker/common-rom.ld> or CONFIG_ZBUS_LINKER_INSERT. Not ported: multi-domain proxy agent (experimental upstream); direct ISR publishing (use the deferred zbus_isr_pub helper instead). Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR ports the Zephyr RTOS zbus (a many-to-many message bus with
typed channels and decoupled observers) to NuttX, preserving the
original declarative API (
ZBUS_CHAN_DEFINE,ZBUS_LISTENER_DEFINE,ZBUS_SUBSCRIBER_DEFINE,zbus_chan_pub/read/notify, ...) so thatexisting Zephyr application code and documentation translate directly.
Original zbus by Rodrigo Peixoto (Apache-2.0); copyright preserved in
the derived files.
Ported features: listeners (synchronous callbacks), subscribers
(queue of channel references), message subscribers (ordered message
copies), async listeners (callback on the LP work queue), a deferred
ISR-safe publisher (
ZBUS_ISR_PUBLISHER_DEFINE/zbus_isr_pub),runtime observers, per-observation notification masks, observer
enable/disable, message validators, channel user data, publish
statistics, lookup by name/id and channel/observer iteration.
Everything is built on native NuttX primitives, with no compatibility
shim layer:
k_semchannel lock + priority boost (HLP)sem_t+ nativeCONFIG_PRIORITY_INHERITANCEk_msgq/k_fifo+net_bufpoolsfile_mq_*), lazy-opened;mqpayload copy replacesnet_bufentirelyk_workwork_queue()(LP queue)SYS_INITpthread_once()include/nuttx/iterable_sections.h(companion PR)k_timeout_tCLOCK_MONOTONICdeadlines (ZBUS_NO_WAIT/ZBUS_FOREVER)Board integration (why one linker-script line matters here)
In Zephyr, zbus works on every board out of the box because boards have
no linker scripts: a single common per-arch linker template already
includes the shared
common-rom.ld/common-ram.ldfragments where thezbus iterable sections are collected. In NuttX each board owns its
.ld,so an adopting board needs one of:
#include <nuttx/linker/common-{rom,ram}.ld>lines in its boardscript (done for
linum-stm32h753bi, the first adopter, in thecompanion PR), or
CONFIG_ZBUS_LINKER_INSERT=y(zero-touchINSERT AFTERmode, withthe MEMORY-region constraint documented in the companion PR).
This is documented in the Kconfig help, in
README.rstand in theSphinx page added by the companion PR.
Also included:
examples/zbus(CONFIG_EXAMPLES_ZBUS): a runnable demo with one channel,one listener, one subscriber, runtime masking.
testing/zbus(CONFIG_TESTING_ZBUS): a cmocka suite, 16 testscovering the full API surface: pub/read/listener/subscriber,
multi-channel index isolation, validators, message subscribers
(ordered copies), bit-exact float/double payload delivery
(sensor-style message with a float-math validator rejecting
non-finite samples), claim/finish/notify, masks, enable/disable,
runtime observers (error paths included), async listeners (bursts),
ISR publisher, from_name/from_id, iteration, accessors, and
timeout/overflow semantics.
Not ported (documented in the "Not ported" section of the docs):
multi-domain proxy agent (experimental upstream), direct publishing from
ISRs (the deferred
zbus_isr_pubhelper covers the use case), thepriority-boost/HLP scheme (superseded by native priority inheritance)
and the
net_bufpool machinery (unnecessary with mq payload copies).Impact
CONFIG_ZBUS, defaultn); no impactwhen disabled.
file_mq_*so queuessurvive the creating task, since
mqd_tis a per-task fd in NuttX);CONFIG_MQ_MAXMSGSIZE >= sizeof(pointer) + CONFIG_ZBUS_MSG_SUBSCRIBER_MAX_MSG_SIZEwhen message subscribers areenabled (checked and documented in Kconfig); board linker integration
as described above.
the upstream zbus diagrams, Apache-2.0) lands with the companion
nuttx PR.
retained.
Testing
Host: Ubuntu 24.04.4 x86_64, Arm GNU Toolchain 13.2.rel1
(arm-none-eabi-gcc 13.2.1).
Target: linum-stm32h753bi:zbus (STM32H753BI; board configuration
added by the companion nuttx PR):
CONFIG_ZBUSwith all optionsenabled (message/async/ISR observers, runtime observers),
CONFIG_EXAMPLES_ZBUS,CONFIG_TESTING_ZBUS. Flashed via ST-LINK V3;console on the ST-LINK VCP.
Example (
zbus): 5 messages published; listener correctly skips themasked message #4; listener notified before the subscriber (observer
priority order):
cmocka suite: 16/16 passing, run twice in the same boot (guards
against the lazy-init/fd-lifetime regression class):
(The
could not notify observer: -42line duringtest_timeoutsis theexpected
-ENOMSGqueue-overflow path being exercised.)Builds: Make (
make -j) and CMake (cmake -GNinja+ninja) bothOK for the target config;
_zbus_*iterable-section symbols verified inthe map on both. Stock build with
CONFIG_ZBUSdisabled: no zbussections/symbols (no-op).
tools/checkpatch.sh -gon the commit: allchecks pass.
The companion nuttx PR adds a
linum-stm32h753bi:zbusboardconfiguration reproducing this exact run
(
./tools/configure.sh linum-stm32h753bi:zbus); since that defconfigenables Kconfig symbols introduced here, the two PRs should land
together.