A small rant on a missing low power implementation. Lots of links and opinions, but I did not want to lose how I found this information, so I figured I'd write this gist.
Zephyr PM API is awesome. You can power down unused peripheral. Manpage HERE.
A repo where I walk through a lot of this: LINK along with a helpful diagram from the manpage on the device pm state machine.
Maybe this is your first foray into Zephyr, and you're using a Nordic board. You want to collect that sensor data and pipe it out via Bluetooth Low Energy (BLE) and are sensitive to power since you're on a battery. Pretty typical use case.
You're flying through your application, everything BLE just works, everythings working great.
You add Zephyr Device PM. You power down peripherals when not in use on the Nordic board and see the power consumption drop when you use the API. Sweet!
Alright, let's shop for a sensor...
and say you find everything you need in this IIS2DLPC from ST!
And the driver is already committed to the Zephyr project? NICE!
Less work is always better, time to knock that sprint review out of the park.
A few lines of code later, you're reading all the data as expected.
But power consumption is a few hundred uA higher than you'd like. Luckily, you've solved this problem earlier in the program, time to add device pm again.
It's only two lines of code! You wrap your usage in the expected
pm_device_action_run(i2c_device, PM_DEVICE_ACTION_RESUME);
and
pm_device_action_run(i2c_device, PM_DEVICE_ACTION_SUSPEND);
Builds and runs, just like before. AWESOME!
Device power doesn't change.
Time to shake your fist at the sky (or Zephyr)?
Did you make the wrong Zephyric incantation to summon the almighty arbiter of power?
Undo changes, test, PM works, diff the code, no it was definitely used correctly...
A handful of
git reset hard
s andgit checkout -b powermanagementmethod13123
's, a pot of coffee and a conversation later and you are convinced it isn't your fault.
Let's dig deeper into the driver that was committed to Zephyr.. Maybe the init..
Hold on, something isn't quite right..
What is that NULL
?
Oh.
Right on. PM wasn't implemented for that device driver. That'd explain why the power didn't change.
Just because there's potentially a vendor supplied driver in Zephyr doesn't mean they implemented everything if there isn't an enforcement or guideline for it. Always check the driver!
Nordic Semi usually did a pretty good job implementing power management since low power is their thing, so the pm working every step of the way led me to ask a second opinion and dig deeper into the driver.
But if it was the first peripheral you added to the project and was trying to get power management working? You would have spent a good chunk of time looking up and down the Zephyr document page over and over again... for no reason.
The conclusion for this blog/rant was to swap to a sensor that met the specs I needed but the PM API was already implemented, since picking a new sensor wins me some time to work on other things. But if you were stuck on the device, you would have had to implement that PM API.
Not all credit is mine. The section on swearing I did something wrong with the code was very much what happened, as I tend to immediately assume fault in my code.
@inductivekickback
(Daniel Veilleux) talked me into looking at the Zephyr driver implementation instead of thinking I did something wrong in the code.