You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Table 7-38 (section 7.6.27) types the IIN_DPM field R and the register
figure shows R-C8h. Without an access annotation the register inherited
default-access: RW from the device block, so the driver generated
write_async and modify_async for a register the silicon never accepts
writes to. A caller reading IIN_DPM as "the input current limit" would
write it and silently achieve nothing.
Annotate the register and its field RO, matching how ADC_VBAT and the
other read-only registers in this manifest are already declared.
Assisted-by: OpenCode:claude-opus-5
Tables 7-43 and 7-44 (sections 7.6.32 and 7.6.33) type both ID fields R
and show R-40h and R-9h in the register figures. Both registers were
inheriting default-access: RW, so the driver generated write accessors
for identification registers that cannot be written.
Annotate both registers and their fields RO, and fold the documented
reset values into the doc comments.
Assisted-by: OpenCode:claude-opus-5
Table 7-57 (section 7.6.46) types STAT_IDCHG2 and STAT_PTM as R, and
Table 7-58 (section 7.6.47) types STAT_VBUS_VAP as R. All three were
left writable, so the generated API offered setters that the silicon
ignores and that suggested a latched status could be cleared by
writing it. Section 7.6.46 says the latch clears on read instead.
Annotate the three fields RO and say so in their doc comments. The
neighbouring STAT_PKPWR_RELAX and STAT_PKPWR_OVLD bits stay writable
because Table 7-48 really does type those R/W.
Assisted-by: OpenCode:claude-opus-5
Table 7-49 (section 7.6.38) names bit 7 of REG0x34 BATFET_ENZ: "Turn
off BATFET under battery only low power mode." The manifest carried
the name PKPWR_TOVLD_DEG here, copy-pasted from the unrelated field in
CHARGE_OPTION_2. The bit position and the doc comment were right, only
the identifier was wrong, so charge_option_3().set_pkpwr_tovld_deg(true)
turned off the BATFET and grepping the driver for BATFET_ENZ found
nothing.
Assisted-by: OpenCode:claude-opus-5
Table 7-30 (section 7.6.19) spells the upper four MODE_STAT encodings
"NA/Normal Compensation/Fsw-600kHz" and so on; the phase topology is
explicitly not applicable. Table 7-1 only makes 000b-011b reachable
through MODE pin programming, and all four of those are quasi dual
phase.
The manifest named 100b-111b SinglePhase*, asserting a topology the
datasheet does not. Rename them Na* so the generated enum stops
claiming more than the source does, and record the caveat in the
field's doc comment.
Assisted-by: OpenCode:claude-opus-5
VRECHG, VSYS_TH1, IDCHG_TH1, VSYS_TH2 and VBUS_VAP_TH all carry a step
and an offset that the manifest recorded nowhere, so a field value of
zero does not mean zero for any of them. IDCHG_TH1 is the worst: it is
a discharge-current PROCHOT threshold with a 1500mA offset and a 500mA
step, so reading it as raw milliamps puts the trip point 1.5 A off.
device-driver cannot express scaling, so the doc comment is the only
place this can live, and it is where anyone about to hand-roll the
conversion will look.
Sources: Table 7-28 (7.6.17) VRECHG, step 50mV offset 50mV; Table 7-51
(7.6.40) VSYS_TH1, step 100mV offset 5000mV; Table 7-54 (7.6.43)
IDCHG_TH1, step 500mA offset 1500mA; Table 7-59 (7.6.48) VSYS_TH2,
step 100mV offset 5000mV; Table 7-60 (7.6.49) VBUS_VAP_TH, step 100mV
offset 3200mV.
Assisted-by: OpenCode:claude-opus-5
Table 7-39 (section 7.6.28) and Table 7-42 (section 7.6.31) both give
"Bit Step: 2mV" and "Range: 0mV-65534mV" for these two channels. The
ADC_VBAT, ADC_PSYS and ADC_CMPIN_TR channels sitting next to them in
the manifest are 1mV/bit, so the natural assumption is wrong by a
factor of two and nothing in the driver said otherwise.
Record the step and range, and point out the difference from the
neighbouring channels.
Assisted-by: OpenCode:claude-opus-5
These three fields are enumerated in the datasheet but were left as
bare uints, which is out of step with the roughly forty other enums in
this manifest and leaves the caller to look the encodings up by hand.
Table 7-52 (section 7.6.41) gives ILIM2_VTH thirty-two levels from
110% to 450%, with 00000b and 11111b both marked out of range. Table
7-57 (section 7.6.46) gives IDCHG_TH2 eight levels from 125% to 400%
of IDCHG_TH1. Table 7-58 (section 7.6.47) gives VSYS_UVP eight levels
from 2.4V to 8.0V.
Bit positions and reset values are unchanged; only the encodings are
now expressed in the type.
Assisted-by: OpenCode:claude-opus-5
The YAML-to-DDSL conversion left a working note wedged between
CMPIN_TR_SELECT's doc comment and the field it documents, splitting
the two.
The decision it records is worth keeping: device.yaml had these three
one-bit selections as base: int, a one-bit signed field sign-extends
so the 1 variant loads back as -1, and the v1 codegen then performed
try_into().unwrap_unchecked() on it, which is undefined behaviour.
Hoist the note above the doc comment and name the other two fields it
covers.
Assisted-by: OpenCode:claude-opus-5
Table 7-15 (section 7.6.4) notes that writing 0 to CHARGE_VOLTAGE()
leaves the register unchanged and forces CHARGE_CURRENT() to zero to
disable charge, and that non-zero values outside the clamp are set to
the clamp. Neither behaviour was documented, so charging_voltage(0)
looked like a request for 0 V and returned the still-programmed
voltage with no explanation.
Record both behaviours on the DDSL field and on the Charger impl, and
add a test pinning the read-back a caller actually gets for a zero
write.
Assisted-by: OpenCode:claude-opus-5
Several doc comments in device.ddsl ran to 300-plus columns on a
single line, which made the register definitions hard to read in a
diff and inconsistent with the 120-column limit the Rust sources are
held to. DDSL joins consecutive /// lines into one doc comment, so
wrapping costs nothing.
Rewrap every /// line so no comment exceeds 80 columns, and regenerate
src/device.rs. Unwrapping the result reproduces the previous file byte
for byte; no documented behaviour changed. The handful of remaining
long lines are field declarations whose enum names cannot be broken.
Assisted-by: OpenCode:claude-opus-5
The doc comment said "with 5mΩ sense resistor, in 8mA/bit steps" as if
the step were fixed. Table 7-14 (section 7.6.3) says the step is 8mA
over 0mA-16320mA (0h-7F8h) only at 5mΩ, and notes that when 2mΩ is
chosen at RSNS_RSR=1b the LSB is 20mA and the value is clamped at 5DCh,
or 30A. RSNS_RSR lives in CHARGE_OPTION_1 and is documented in Table
7-46 (section 7.6.35).
The driver already picks the right scaling factor from RSNS_RSR, so
this is the manifest catching up with src/lib.rs rather than a
behaviour change. Also record the 128mA floor on non-zero settings,
the clamping behaviour, and the seven conditions under which the
charger resets this field to 0A, all from the same table.
Assisted-by: OpenCode:claude-opus-5
The new documentation promises that every non-zero request below 5000 mV is clamped, but requests of 1–3 mV are integer-divided by 4 at line 170 and become the special zero write. The device therefore leaves the old voltage unchanged and disables charging instead of clamping to 5000 mV. Clamp before scaling (while preserving the explicit 0 case), or document/reject this range accurately.
Unrelated to this PR, but it surfaced during review: 0.1.0 and 0.1.1 should be yanked.
Both write raw milliamps and millivolts straight into scaled register fields:
CHARGE_CURRENT is 8 mA/LSB (§7.6.3, Table 7-14) → every charge current is 8× too high. Ask for 1000 mA, get 8000 mA.
CHARGE_VOLTAGE is 4 mV/LSB in a 13-bit field (§7.6.4, Table 7-15) → values truncate. A 3S pack asking for 12600 mV gets regulated at 17632 mV. That's a legal value for the chip, so the clamp doesn't save you — it's just wrong for the cell count.
So: an 8× overcurrent and a ~5 V overvoltage into a 2–5 cell Li-ion pack, both in the damaging direction. Only EN_BATOVP stands between the second one and cell damage.
Yanking looks cheap — zero reverse dependencies on crates.io, and 0.1.1 traffic dropped to ~zero the day 0.2.0 shipped. A yank doesn't break existing Cargo.lock builds, it only stops new resolution onto the affected versions.
## 🤖 New release
* `bq25773`: 0.2.1 -> 0.3.0
<details><summary><i><b>Changelog</b></i></summary><p>
<blockquote>
##
[0.3.0](v0.2.1...v0.3.0)
- 2026-10-07
### Other
- [**breaking**] Migrate to device-driver 2.1
([#29](#29))
</blockquote>
</p></details>
---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.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
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.
Adopt DDSL, regenerate bindings, and update CI and audits. Upgrade to defmt 1 and bump the crate to 0.3.0.
BREAKING CHANGE: Update the register API and require Rust 1.94.
Assisted-by: GitHub Copilot:gpt-6-astra
Uprev to v0.3.0, will cargo publish after merge.