i2c: phase 4 — WaitGroup interrupt loop + slave notification dispatch

Replace the single-channel object_wait with a WaitGroup that multiplexes
two sources on the i2c_server main loop:

  user_data=0  IPC from client  (Signals::READABLE on handle::I2C)
  user_data=1  I2C2 hardware interrupt (signals::i2c2 on handle::I2C2_IRQ)

Server startup registers both sources once via wait_group_add, then
calls object_wait(WG, READABLE, Instant::MAX) as the single blocking
point. When the WaitGroup fires:

  • user_data 1 (interrupt): call drain_slave_rx() for every
    notification-enabled bus, interrupt_ack() the IRQ, then
    raise_peer_user_signal() to wake the registered client.

  • user_data 0 (IPC): dispatch as before; two new ops added:
    - EnableSlaveNotification  → backend.enable_slave_notification()
    - DisableSlaveNotification → backend.disable_slave_notification()
    SlaveReceive now calls get_buffered_slave_message() (non-blocking)
    instead of the 10 000-iteration poll loop.

system.json5 changes (both i2c-slave and i2c targets):
  - Add I2C2_IRQ interrupt object (IRQ 112, name "i2c2")
  - Add WG wait_group object

channel_read/channel_respond remain synchronous: by the time the
WaitGroup fires with user_data=0 the channel is already READABLE, so
channel_read returns immediately without blocking.
3 files changed
tree: a70514dfa14fcaa7b9949e00de76b79184933d92
  1. .cargo/
  2. .github/
  3. apps/
  4. docs/
  5. hal/
  6. openprot/
  7. patches/
  8. platform/
  9. services/
  10. target/
  11. third_party/
  12. xtask/
  13. .bazelignore
  14. .bazelrc
  15. .bazelversion
  16. .gitignore
  17. .semgrepignore
  18. BUILD.bazel
  19. BUILD.md
  20. Cargo.lock
  21. Cargo.toml
  22. deny.toml
  23. LICENSE
  24. MODULE.bazel
  25. MODULE.bazel.lock
  26. out-of-tree.md
  27. port-mctp-echo.md
  28. pw
  29. README.md
  30. rust-toolchain.toml
  31. workflows.json
README.md

OpenPRoT

Technical Charter

The OpenPRoT Technical Charter can be found at https://github.com/OpenPRoT/.github/blob/main/GOVERNANCE.md

Getting Started

This project uses cargo-xtask for build automation and project management.

Available Tasks

You can run tasks using cargo xtask <task-name>:

  • cargo xtask build - Build the project
  • cargo xtask test - Run all tests
  • cargo xtask check - Run cargo check
  • cargo xtask clippy - Run clippy lints
  • cargo xtask fmt - Format code with rustfmt
  • cargo xtask clean - Clean build artifacts
  • cargo xtask dist - Build a distribution (release build)
  • cargo xtask docs - Build documentation with mdbook
  • cargo xtask cargo-lock - Manage Cargo.lock file
  • cargo xtask precheckin - Run all pre-checkin validation checks
  • cargo xtask header-check - Check license headers in source files
  • cargo xtask header-fix - Fix missing license headers in source files

Examples

# Build the project
cargo xtask build

# Run tests
cargo xtask test

# Create a distribution
cargo xtask dist

# Format code
cargo xtask fmt

# Run clippy
cargo xtask clippy

# Build documentation
cargo xtask docs

# Run all pre-checkin validation checks
cargo xtask precheckin

# Check license headers
cargo xtask header-check

# Fix missing license headers
cargo xtask header-fix

Development

The project is structured as a Cargo workspace with two main components:

  • openprot/ - The main application
  • xtask/ - Build automation scripts

The xtask workflow allows you to add custom build steps, automation, and project management tasks written in Rust, making them cross-platform and easy to maintain.

Requirements

  • Rust 1.70+ (2021 edition)
  • Cargo

No additional tools are required - everything is handled through Cargo and the xtask scripts.