Skip to content

Fix review issues#7

Merged
snabb merged 49 commits into
mainfrom
fix/review-issues
May 5, 2026
Merged

Fix review issues#7
snabb merged 49 commits into
mainfrom
fix/review-issues

Conversation

@snabb
Copy link
Copy Markdown
Owner

@snabb snabb commented May 5, 2026

No description provided.

snabb and others added 30 commits April 26, 2026 11:29
PhantomData<fn() -> ()> is Send + Sync, so it did not prevent
Bmi323Async from implementing Sync as the comment claimed.
PhantomData<Cell<()>> is Send + !Sync, correctly preventing Sync.
All fields (u8, StatusWord, ErrorWord) implement Eq, but
DeviceState was missing the Eq derive.
Add missing assertions for significant_motion (bit 6),
gyro_data_ready (bit 12), and accel_data_ready (bit 13),
and expand the false-assertion block for InterruptStatus(0).
The configure_interrupt_pin method uses matches! to map these enum
variants to register bit values. Without explicit discriminants,
reordering the variants would silently break the bit assignments.
Replace hard-coded addresses 0x0D, 0x0E, 0x0F in read_interrupt_status
with named INT_STATUS_INT1, INT_STATUS_INT2, INT_STATUS_IBI constants
matching the pattern used by every other register in the driver.
The transport layer's fixed-size stack buffer already catches oversized
reads with a slice bounds panic. Using debug_assert! preserves detection
in debug builds while avoiding redundant checks in release.
The STM32G030F6 example binaries were not being formatted or linted
in CI. Added cargo fmt --check and cargo clippy steps. Fixed
pre-existing formatting issues in the example source files.
AccelConfig and GyroConfig already implement Default. Adding it to
FifoConfig with all data streams disabled provides a consistent
starting configuration that matches the hardware reset state.
AccelConfig and GyroConfig already implement Default. Adding it to
FifoConfig (derived since all fields are bool defaulting to false)
provides a consistent starting configuration that matches the
hardware reset state.
PhantomData<Cell<()>> prevented wrapping the driver in Mutex/RefCell for
sharing across Embassy tasks, which is a common embedded pattern. The
blocking Bmi323 had no such marker. The async driver has no invariant
that requires !Sync, so the restriction is removed.
After a soft reset ACC_CONF and GYR_CONF read 0x0000, meaning the
on-chip range bits are G2 and Dps125. The driver was caching G8/Dps2000
as the startup defaults, so as_g()/as_dps() calls made before any
set_accel_config()/set_gyro_config() would apply the wrong scale factor.

Change the initial cache values to G2/Dps125 to match the actual
hardware POR state and update all associated documentation.
0x012C (feature engine config payload), 0x0001 for FEATURE_IO_STATUS sync
trigger and FEATURE_CTRL enable, and the CMD opcodes SOFT_RESET/SELF_TEST
now have documented named constants in registers.rs referencing the
relevant datasheet sections.
InterruptSource::I3cSync existed and could be routed to an interrupt
channel, but InterruptStatus had no corresponding bit-9 accessor.
Added i3c_sync() and a matching test.
The BMI323 INT_STATUS register bit 10 is named err_status in the
datasheet; it routes the error-engine status, not a generic
feature-engine event. The previous name FeatureStatus was misleading.

Renamed:
- InterruptSource::FeatureStatus -> InterruptSource::ErrorStatus
- InterruptStatus::feature_status() -> InterruptStatus::error_status()
The magic literal 64 appeared four times across transport.rs scratch
buffers. Replaced with the public constant MAX_WORDS_PER_READ so the
limit is named in one place.

Also promoted debug_assert! to assert! in read_fifo_words: in release
builds a slice over the 64-word scratch buffer would still panic via
index bounds, so the assert! is not an extra cost—it just gives a
clearer message earlier.
FIFO_WATERMARK is a 10-bit field (range 0..=1023) per BMI323 datasheet
§6.11.17; the existing & 0x03FF mask is correct. FIFO_FILL_LEVEL is a
separate 11-bit field (0..=2047), consistent with the & 0x07FF mask.

Added doc comments on set_fifo_config explaining the truncation, and
added a comment citing the datasheet section at the mask site.
Previously the loop slept 10 ms before the first status read. Self-test
typically completes in ~30 ms; reading first avoids an unnecessary 10 ms
delay when the result is already available early in the polling window.
BMI323 datasheet Table 3 specifies t_start = 2 ms typical after a
soft reset. The 2 ms delay is correct; added a comment so the origin
is clear to future readers.
…s errors

On a fast SPI bus, back-to-back polls of FEATURE_IO1 could exhaust the
32-iteration window before the feature engine reaches a ready state (0x1
or 0x5), causing false FeatureEngineNotReady errors. Added a 200 µs delay
between iterations, mirroring the pacing used in run_self_test_inner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The BMI323 datasheet (§5.9) defines raw TEMP_DATA value 0x8000 as
"invalid temperature", returned when no valid sample is available yet.
Previously read_temperature_celsius silently converted it to ~−41 °C.

Add Error::InvalidTemperature, extract a shared temperature_raw_to_celsius
helper in driver.rs, and return the new error variant when the sentinel is
detected. Covered by three new unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…types

Every constant in registers.rs now carries a §6.1.2 / §6.2.2 inline
comment pointing to its exact register entry in the BMI323 datasheet
(BST-BMI323-DS000-12). Three existing references that cited non-existent
section numbers (§6.11.37, §4.5, §6.11.25) are corrected.

Every public type and enum in types.rs now has a §-prefixed reference in
its doc comment linking it to the register field(s) and/or functional
description section that defines its encoding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bit fields

Add §-prefixed BST-BMI323-DS000-12 citations to all remaining code paths
that were missing them:

- driver.rs: fix temperature_raw_to_celsius doc (wrong §5.9 → §6.1.2
  Register (0x09) temp_data; §5.6.3); cite formula source
- types.rs: cite §5.6.1/§5.6.2 for the 32768 divisor in
  scale_g_per_lsb / scale_dps_per_lsb
- blocking_driver.rs: fix §6.11.17 → §6.1.2 Register (0x35) for
  FIFO_WATERMARK; add §6.1.2 Register (0x15) for fill-level mask;
  add §5.7.4 for FIFO flush; add §6.1.2 Register (0x11) for
  FEATURE_IO1 self-test bits; add §6.2.2 Register (0x02) for
  EXT_GEN_SET_1 field layout; add §6.1.2 Register (0x10) bit-assignment
  table for FEATURE_IO0
- transport.rs: cite §7.2.3 for SPI read-bit encoding and dummy bytes;
  cite §7.2.4.2 for I2C dummy bytes (both blocking and async paths)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merged src/async_driver.rs and src/blocking_driver.rs (~1800 lines,
~700 lines of which were mechanical async/await duplication) into a
single src/driver_impl.rs (~975 lines) using the maybe-async 0.2.10
crate. Cargo feature flags select the mode: `blocking` (default,
enables maybe-async/is_sync) or `async` (enables embedded-hal-async).
Enabling both simultaneously is a compile error.

The public API changes: Bmi323Async is removed; Bmi323 serves both
modes. All examples, embassy-stm32g030f6-examples, and integration
tests are updated accordingly.

CI is also fixed: --all-features was a compile error with the new
mutually exclusive feature flags. Each check/test step now runs
explicitly with --features blocking and --no-default-features
--features async. Coverage merges both runs before upload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The self-test modified accel/gyro config and feature engine state and
then restored them afterwards, adding 6 I2C reads and 6 writes around
every test run. Instead, document that the sensor is in an undefined
configuration after the self-test and the caller must reconfigure as
needed. This aligns with how init() behaves (no implicit state assumptions).

Also inlined run_self_test_inner into run_self_test since the wrapper
was now a trivial single-call passthrough.

Updated tests to match the new transaction sequence and removed the
now-obsolete restore-error tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously pin.wait_for_high() errors were silently dropped with .ok(),
meaning callers could not distinguish a GPIO failure from a successful
wait. The underlying GPIO error value cannot be preserved in Error<E>
without a second type parameter, so a unit variant is used instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0x1 and 0x5 are the BMI323 feature_io1 error_status values for
"initialization successful" and "no error / normal running state".
Named constants make the intent clear at the call site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The BMI323 datasheet (§6.1.2, Register (0x11) feature_io1) defines 13
error_status values. Previously only 0x01 and 0x05 were named. Added
the full set for reference. Also renamed FEATURE_ENGINE_STATUS_INIT_OK
to FEATURE_ENGINE_STATUS_ACTIVATED to match the datasheet wording.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two remaining magic numbers: 0x0001 written to FIFO_CTRL to trigger a
flush, and 13 used as the maximum interrupt hold-time exponent in three
places. Replace with named constants for clarity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The enum currently fits in 4 bits (values 0..=9) but the two nibble
fields were packed without masking. A future variant above 15 would
silently corrupt the adjacent nibble. Mask defensively with & 0x0F.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
snabb and others added 17 commits May 4, 2026 18:21
…onfig

Writing to ACC_CONF or GYR_CONF returns the sensor from its alternate
configuration when AltConfigControl::reset_on_user_config_write is set.
This is non-obvious side-effect worth documenting on both methods.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Blocking example imported AccelMode, AccelRange, AverageSamples,
Bandwidth, GyroMode, GyroRange but used none of them. Async example
imported AccelRange, AverageSamples, Bandwidth but used none of them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…atus constants

The FEATURE_ENGINE_STATUS_* constants document all datasheet-defined
FEATURE_IO1.error_status values (§6.1.2, Register 0x11). Most are not
referenced in driver logic but are kept as documentation. Add per-constant
#[allow(dead_code)] to silence the compiler warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erConfig

- ActiveLevel and OutputMode get #[derive(Default)] with Low/PushPull as
  defaults (matching BMI323 power-on reset state), which enables
  InterruptPinConfig to also derive Default (enabled: false, low, push-pull)
- MotionAxes gets a manual Default returning XYZ — the all-false derive
  default would be useless for motion detection
- StepCounterConfig gets Default delegating to disabled(), keeping the two
  in sync

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the four separate test files (blocking_i2c_transactions,
async_i2c_transactions, blocking_spi_transactions, async_spi_transactions)
with two shared source files (i2c_transactions.rs, spi_transactions.rs),
each compiled twice — once per feature — via Cargo.toml [[test]] entries
that point the same `path` under different names.

The shared files use two small macros:
- `run!(expr)` — evaluates directly in blocking mode, drives via block_on
  in async mode, replacing every block_on(...) call
- `delay_tx!(ms/us, n)` — produces the right DelayTransaction variant for
  the active feature

Additional improvements:
- Switch from the loose `TestDelay` (no assertions) to `CheckedDelay` for
  all blocking tests that involve delay calls, giving them the same strict
  validation already present in the async tests. Error-path tests (init
  failures) now also validate the 2 ms soft-reset delay.
- The enable_feature_engine success test (previously used NoopDelay in both
  variants) now validates the single 200 µs pre-poll delay.
- Fill async SPI parity gaps: add spi_feature_engine_enable and
  spi_any_motion_configuration tests that were present only in blocking SPI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows users to use Error<E> with Box<dyn Error> and ? into anyhow/eyre
without manual wrapping. core::error::Error is stable since Rust 1.81,
within our MSRV of 1.85.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eatures

cargo build --features async silently activates both blocking (default)
and async, producing 49 cryptic type errors. The guards now emit a clear
actionable message as the first error so users know exactly what to fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-features

Async is now the implicit default — adding the crate with no feature flags
gives the async driver. Blocking users must opt out explicitly:

  bmi323-driver = { version = "...", default-features = false, features = ["blocking"] }

This matches the modern embedded-rs convention where Embassy/async is the
primary target. The compile_error guards and CI commands are updated to
reflect the new default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The feature flag design is now:

  default = []          # async behaviour when nothing is specified
  async   = []          # explicit no-op marker; gates async examples/tests
  blocking = [...]      # opts into synchronous embedded-hal API

Library users:
  bmi323-driver = "0.2"                          # async (default)
  bmi323-driver = { ..., features = ["async"] }  # async (explicit)
  bmi323-driver = { ..., features = ["blocking"] } # sync — no
                                                    # default-features = false
                                                    # needed

embedded-hal-async is now a hard dependency (thin trait crate); blocking
users who want to exclude it can still use default-features = false.

All cfg(feature = "async") / cfg(not(feature = "async")) guards in src
and tests are replaced with cfg(not(feature = "blocking")) /
cfg(feature = "blocking") so correctness depends only on the blocking
feature rather than an explicit async opt-in.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each [[test]] target now has its own thin wrapper file that include!s
the shared implementation, giving Cargo a unique path per target.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… POR

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 84.37500% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.78%. Comparing base (0efcf04) to head (261a32d).

Files with missing lines Patch % Lines
src/types.rs 21.42% 22 Missing ⚠️
src/driver.rs 58.82% 7 Missing ⚠️
src/driver_impl.rs 99.09% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #7      +/-   ##
==========================================
- Coverage   99.13%   96.78%   -2.35%     
==========================================
  Files           6        5       -1     
  Lines        1846     1245     -601     
==========================================
- Hits         1830     1205     -625     
- Misses         16       40      +24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@snabb snabb merged commit 2d95b5a into main May 5, 2026
3 of 5 checks passed
@snabb snabb deleted the fix/review-issues branch May 5, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant