Skip to content

Add Fuel Gauge driver to zephyr::device#167

Open
bjackson312006 wants to merge 6 commits into
zephyrproject-rtos:mainfrom
bjackson312006:fuel-gauge
Open

Add Fuel Gauge driver to zephyr::device#167
bjackson312006 wants to merge 6 commits into
zephyrproject-rtos:mainfrom
bjackson312006:fuel-gauge

Conversation

@bjackson312006

Copy link
Copy Markdown

This PR adds a zephyr::device::fuel_gauge module (located at zephyr/src/fuel_gauge.rs) that implements a safe Rust wrapper around the Zephyr fuel gauge API. This PR also adds a simple fuel_gauge sample to demonstrate this driver.

Since Zephyr's fuel gauge API is based around the fuel_gauge_prop_val union, this driver was designed to expose all the same data but via explicit accessors for each field/property. The C fuel_gauge_prop_t type was adapted into pub(crate) enum FuelGaugeProp and pub(crate) enum FuelGaugeBufferProp, which are meant to provide some internal type safety for the rest of the driver. These enums map directly to the autogenerated crate::raw::fuel_gauge_prop_type module. 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_type were 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(), and pub(crate) fn get_buffer_prop(). These helpers are meant to isolate the main unsafe blocks in the driver, and allow the rest of the driver to use the safe FuelGaugeProp and FuelGaugeBufferProp types when requesting data. TLDR they provide safer internal wrappers for the raw fuel_gauge_get_prop(), fuel_gauge_set_prop(), and fuel_gauge_get_buffer_prop() calls to the C API.

After that, there's the ManufacturerName, DeviceName, and DeviceChemistry types, which each wrap around a heapless::String. This adds a dependency (heapless), but significantly improves the interface of the user-facing manufacturer_name(), device_name(), and device_chemistry() functions since users no longer need to manually pass in a mut buffer for the calls to write into. Plus, a String is 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 aforementioned manufacturer_name(), device_name(), and device_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 safe get_prop()/set_prop() helpers for their respective FuelGaugeProp, and then access the returned union prop in a small unsafe block. I looked into moving these unsafe blocks directly into get_prop() and set_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_gauge sample 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 derive Debug, including ManufacturerName, DeviceName, and DeviceChemistry.

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 kurtjd left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, very good, though a few things I think are worth addressing.

Comment thread samples/fuel_gauge/boards/mimxrt685_evk_mimxrt685s_cm33.conf Outdated
Comment thread samples/fuel_gauge/boards/native_sim_native_64.conf Outdated
Comment thread samples/fuel_gauge/src/lib.rs
Comment thread zephyr/src/device/fuel_gauge.rs
Comment thread zephyr/src/device/fuel_gauge.rs Outdated
Comment thread zephyr/src/device/fuel_gauge.rs Outdated
Comment thread zephyr/src/device/fuel_gauge.rs Outdated
Comment thread zephyr/src/device/fuel_gauge.rs Outdated
Comment thread samples/fuel_gauge/CMakeLists.txt Outdated
Comment thread zephyr/src/device/fuel_gauge.rs
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>
@bjackson312006
bjackson312006 requested a review from kurtjd July 20, 2026 22:07
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>
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.

2 participants