Unable to obtain low power use when idle

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:

/resized-image/__size/2080x2070/__key/communityserver-discussions-components-files/4/pastedimage1693836927606v3.png

  • Hi Rogier, I just wanted to let you know I have started looking into this.

  • Here is a quick update with a couple of thoughts that come to mind.

    • The modem will draw a large current (a few mA) if it has not been initialized. After initialized the current will drop to a few uA. (This is listed as an errata/known issue, I will post the link later.)
    • Is the UART disabled in the hello_world sample? Disabling the UART will also make the current drop.
  • Hi Helsing, thanks for your feedback on this!

    Ok.. so the modem current drop has been accounted for Slight smile Good to know that the modem does need to be initialized for any application, even when the modem is not used.

    Does this also explain the 1.5mA draw after setting "REGULATORS.SYSTEM_OFF" to 1 without initializing the modem (i.e. modem power domain isn't touched by this setting)?

    Thing like this (e.g. the need for modem initialization) get lost in the Zephyr examples, as errata like this are handled/fixed "below the hood". The Zephyr example code I used to establish the 4µA baseline only included a single zephyr.h and issued a single printk(), that's it. All device initing is done outside of application's view. In many cases this probably is good thing, but it doesn't help to easily grasp what's really going on...

    On your second note about the UART

    As far as I know, I'm not using the UART, at least not in my application code. Would it be possible the SPM did enable the UART (or some other peripheral)?  And when it does so in Secure environment, I guess I cannot disable it again from a NS application? Given the 1.7mA draw it seems that the HF clock is running, agree?

  • Hi Rogier, sorry for the delay. I understand that you are in contact with our FAE. Please let us know if you would like to continue parts of the discussion here.

Related