Add Fuel Gauge driver to zephyr::device#167
Open
bjackson312006 wants to merge 6 commits into
Open
Conversation
Added fuel_gauge.rs driver to device module. This driver is a pretty straightforward wrapper around Zephyr's union-based C API for fuel gauges, and mainly serves to provide safe getters (and certain setters) to the union props. The only extra/"fancy" stuff added on top are the `manufacturer_name()`, `device_name()`, and `device_chemistry()` getters, since they return their values in newtypes that wrap around heapless::String. I did this to avoid writing into a user-provided buffer, and for convenience on the user's end. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com> Assisted-by: GitHub Copilot:claude-opus-4.8
Added a samples/fuel_gauge project to demonstrate the fuel_gauge.rs driver. When ran, the sample logs an assortment of important fuel gauge readings using the FuelGauge driver's type-safe getters. This is meant to demonstrate the use of the driver itself, as well as the ease of formatting the data via #[derive(Debug)]. The sample is currently configured for the 'mimxrt685_evk/mimxrt685s/cm33' and 'native_sim/native/64'. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com> Assisted-by: GitHub Copilot:claude-opus-4.8
kurtjd
suggested changes
Jul 17, 2026
kurtjd
left a comment
There was a problem hiding this comment.
Overall, very good, though a few things I think are worth addressing.
Added license headers for fuel_gauge sample and fuel_gauge.rs driver. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com>
Removed unneeded line in samples/fuel_gauge's CMakeLists.txt, and moved ManufacturerName, DeviceName, and DeviceChemsitry structs to the top of `fuel_gauge.rs`. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com>
Fixups in resposne to review by kurtjd. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com>
Moved the configs under `# Fuel Gauge` to the fuel_gauge sample's main `prj.conf`, rather than keeping them duplicated in the board-specific .conf files. Signed-off-by: Blake Jackson <blakejackson312006@gmail.com>
bjackson312006
force-pushed
the
fuel-gauge
branch
from
July 21, 2026 19:42
e93515f to
64a99ba
Compare
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.
This PR adds a
zephyr::device::fuel_gaugemodule (located atzephyr/src/fuel_gauge.rs) that implements a safe Rust wrapper around the Zephyr fuel gauge API. This PR also adds a simplefuel_gaugesample to demonstrate this driver.Since Zephyr's fuel gauge API is based around the
fuel_gauge_prop_valunion, this driver was designed to expose all the same data but via explicit accessors for each field/property. The Cfuel_gauge_prop_ttype was adapted intopub(crate) enum FuelGaugePropandpub(crate) enum FuelGaugeBufferProp, which are meant to provide some internal type safety for the rest of the driver. These enums map directly to the autogeneratedcrate::raw::fuel_gauge_prop_typemodule. This involves some annoying boilerplate, but it's worth it so the raw C constants can be contained in one place without needing to be used internally by the rest of the driver. Plus, these enums will never need changes as long as Zephyr's API stays stable.^^ Note: The depreciated constants in
crate::raw::fuel_gauge_prop_typewere deliberately left out of these enums.Below this, there are some internal helpers used to wrap around the raw Zephyr calls:
pub(crate) fn get_prop(),pub(crate) fn set_prop(), andpub(crate) fn get_buffer_prop(). These helpers are meant to isolate the mainunsafeblocks in the driver, and allow the rest of the driver to use the safeFuelGaugePropandFuelGaugeBufferProptypes when requesting data. TLDR they provide safer internal wrappers for the rawfuel_gauge_get_prop(),fuel_gauge_set_prop(), andfuel_gauge_get_buffer_prop()calls to the C API.After that, there's the
ManufacturerName,DeviceName, andDeviceChemistrytypes, which each wrap around aheapless::String. This adds a dependency (heapless), but significantly improves the interface of the user-facingmanufacturer_name(),device_name(), anddevice_chemistry()functions since users no longer need to manually pass in a mut buffer for the calls to write into. Plus, aStringis a more accurate way to type this data (compared to&mut [u8]) and works better with Debug/Display/fmt.Below that is the main public API, which first includes
is_ready()and the aforementionedmanufacturer_name(),device_name(), anddevice_chemistry()functions used to read buffer props. The functions after that, which make up the vast majority of the public API, are the getters and setters for the single-value union properties. These functions all follow an identical structure: They call the safeget_prop()/set_prop()helpers for their respectiveFuelGaugeProp, and then access the returned union prop in a small unsafe block. I looked into moving these unsafe blocks directly intoget_prop()andset_prop(), but this wasn't possible to do without defeating the purpose of the moves in the first place. However, since these blocks are all tiny, identical, and performing an action we know to be safe (union operations guaranteed to valid per the calls to the Zephyr API), I think this is fine.^^ Note: Not all of the getters have setters since a lot of the fields are only meant to be read
There's no single property to match on for a fuel gauge as far as I know, so I'm just matching on a single property (
"sbs,sbs-gauge-new-api") like flash-controller does. This should be fine for SBS-compatible fuel gauges, but down the line it may be necessary to explore some other way to automatically make this work for all fuel gauges.Aside that, the new
fuel_gaugesample shows how to use the driver by periodically reading a bunch of data from the gauge and logging it. The logging is made easy since all types returned by the driver deriveDebug, includingManufacturerName,DeviceName, andDeviceChemistry.