We have designed and built a battery-powered 'IoT' measurement device, based on the nRF9160 (SICA-B1A, MFW v1.3.3), currently in prototype field-testing phase.
The application is developed in Rust (all our green-field embedded development is done in Rust from 2019 onward) and the application functionally nearly finished. One of the things we're still chasing is the high idle use of the device, measuring ~1.7mA in the MCU power domain. We have been working quite hard to tackle this, but haven't found the culprit yet.
In order to eliminate any parasitic power use of the hardware components in our product, we ended up making a custom board that the is only populated with the nRF9160, a couple of decoupling caps and a SIM slot (no DC/DC psu, no sensors etc..) The goal is to have a "nothing" application, doing nothing expect having an "application" running with the lowest power possible to set the baseline power usage target for when all peripherals are connected in a fully populated/functional product.
When we run the nRF9160 with a 'hello world' type application the power use is (static, flat) 2.7mA @3.3V (the program ends in a WFI(), so CPU should be idle). We tried disabling as much MCU peripherals as possible, with no result: draw remains a steady 2.7mA. What we did find is, that when the modem is initialized, but not enabled (calling `nrf_modem_init` in the nrfxlib), the power use drops by about 1 mA (to 1.7mA). Still way too high, but better... unexpected(!), but better..
Although there's next-to-nothing on our board, we started to doubt our purpose-created hardware; how can it be that a bare-as-bone hardware and software is still drawing a whopping 2.7 mA's.. there has to be something wrong with the hardware.. But lo and behold when we flashed a 'do nothing' (single `printk` in the `main()`) sample using the Zephyr based connect SDK, the power use dropped to 4µA.. that's more like it! (in our final product anything <50µA idle use would be acceptable). At least now we know our hardware is capable of a very low power usage. We fruitlessly invested another couple of hours trying to find what is the culprit, no smoking gun was found why we weren't able to get to this level in our programming environment.
Here's the summary of power uses in different setups, maybe something obvious can be distilled from this(?):
- Without modem initialized
- Idle loop (WFI()): 2.7mA
- REGULATOR System off: 1.5mA
- With modem initialized
- Idle loop (WFI()): 1.7mA
- REGULATOR System off: <100µA
With the modem is initialized and "System OFF mode" (REGULATORS_NS) is enabled we get closer to low power territory at sub 100µA draw, but still nowhere near the 4µA that should be obtainable. Furthermore using the "system off" mode for this is undesirable.
The application is running in Non-Secure mode. Too boot into our Non-Secure app, we use a precompiled SPM binary (from Connect SDK). Another line of thought is that the SPM does something that prevents us to get into the low power modes. The "hello world" example that is running at 4µA uses the TFM, unfortunately I wasn't able to get our application to run by using this TFM image, so I could not test that loader (possibly TFM need some more secure parameters set or in flash?).
All in all there must be some initialization or some disabling we're missing.. Hope anyone can shed some light on this..
Thanks in advance!
Ps. All power measurements are made using a PPK2 as power supply/analyzer. Power supply voltage was set to 3.3 Volt. The DUT was disconnected from the debugger and power-cycled before any measurements were taken.
For completeness the (part of the) schematics which was is populated on the board: