Help with sleeping/low power mode on nRF5340

Hi,

I have been trying to follow the guidance here: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/optimizing-power-on-nrf53-designs

I'm using a custom board with NCS version 1.7.1 and VS Code.

I've been able to get my device to go into PM_STATE_SOFT_OFF, but if I choose any other state, like PM_STATE_STANDBY, it just immediately wakes up.

I've been assuming that it was a peripheral keeping it awake so I've been messing with pm_device_state_set calls, but I found the pm_low_power_devices() function, which puts ALL devices into low power that aren't already there.

I'm on a custom board, but at this point in the debugging process my firmware is very basic. I've commented out everything except the following code, which gets called in a loop:

      printk("S\n");
      k_sleep(K_MSEC(1));  
      pm_low_power_devices();
      pm_power_state_force((struct pm_state_info){PM_STATE_STANDBY,0,0,0});  
      pm_device_state_set((struct device *)(device_get_binding("UART_1")), PM_DEVICE_STATE_ACTIVE);  
      printk("W\n");      
      k_sleep(K_MSEC(1));  

So that code is resulting in me printing S, wait 1ms, W, wait 1ms forever. Interestingly, it doesn't start doing this until exactly 1 second after I plug in power. There is a second processor on this board that's trying to send some SPI traffic to the nRF5340, but at this point I'm not initializing those pins - plus it's not communicating anywhere near as often as this wakeup is happening.

One thing that differs from the blog post example is that I'm running my code in the nonsecure area, because I was under the impression that I had to, so the SPM project is involved. Maybe that's waking me up? Do I need to add  something to the configuration file for SPM?

Second question, which may or may not have anything to do with the above issue:

I have this project building using the nrf5340dk_nrf5340_cpuapp_ns build. I've had both a prj.overlay file and a nrf5340dk_nrf5340_cpuapp_ns.overlay file. As I've been writing this help request, I've been experimenting with those. I was able to get down to a simple set of instructions in the nrf5340dk_nrf5340_cpuapp_ns file and delete the prj.overlay. The behavior is still as I described above.

If I change the filename to prj.overlay instead, my console stops working and I get warnings (those red squiggly lines you can hover over) saying unknown reference to uart_1. When do you use one kind of overlay file vs another? What's the difference?

Here are the contents:

/ {
chosen {
zephyr,console = &uart1;
};
};

&uart1 {
compatible = "nordic,nrf-uarte";
status = "okay";
label = "UART_1";
current-speed = <115200>;
tx-pin = <9>;
rx-pin = <0xFFFFFFFF>;
};

&spi0 {
compatible = "nordic,nrf-spis";
label = "SPI_0";
status = "disabled";
mosi-pin = <22>;
miso-pin = <20>;
sck-pin = <12>;
csn-pin = <34>;
def-char = <0xFF>;
};

Thanks,

Glen

  • A bit more info: I tried adding these to my spm.conf file:

    CONFIG_PM=y
    CONFIG_PM_DEVICE=y
    With CONFIG_PM_DEVICE in there it fails to build. With just CONFIG_PM, it works - but it does not change anything about the behavior I described above.
  • Hi

    Can you describe how you see the immediate wake up when calling the STANDBY? Does the device go to sleep/idle mode at all? Can you also let me know what build error(s) you're seeing if you set CONFIG_PM_DEVICE=y, because this should be enabled to let you do necessary power management operations like turning off device clocks and peripherals. Please also note that it should be set in the prj.conf file, what's this spm.conf file you are using?

    Best regards,

    Simon

  • It's not going to sleep at all.

    Oh - I found the problem, but I don't know the solution:

    pm_power_state_force calls pm_state_set which calls pm_power_state_set, and that function ONLY supports 

    PM_STATE_SOFT_OFF.

    __weak void pm_power_state_set(struct pm_state_info info)
    {
        switch (info.state) {
        case PM_STATE_SOFT_OFF:
            nrf_regulators_system_off(NRF_REGULATORS);
            break;
        default:
            LOG_DBG("Unsupported power state %u", info.state);
            break;
        }

    So how are you supposed to go to the various sleep states? I was hoping to use 

    PM_STATE_SUSPEND_TO_RAM.
    What I really need is to go to the lowest power state possible without losing my place in the code while waiting for a GPIO interrupt to wake me up (When you wake up from SOFT_OFF it's like a system reset where you've lost everything - I want to continue from where I went to sleep).
    The spm.conf file is the configuration file for the Secure Partition Manager - I was just testing adding the power management configuration options to there in case that was required for going to low power mode when using a project with SPM.... turns out that wasn't the issue. My main prj.conf does have the CONFIG_PM_DEVICE setting and it's fine.
  • Hi again Glen

    You have just downloaded the project from the nRF53 power optimization blog post, right? You will need to edit the pm_power_state_set() function to allow I.E. the SUSPEND_TO_RAM state instead of just the SOFT_OFF state.

    In the latest nRFConnect SDK releases (1.9.1) there is a test project doing that \NCS_FOLDER\v1.9.1\zephyr\tests\subsys\pm\device_wakeup_api\src\main.c here. Please give it a look.

    Best regards,

    Simon

  • You will need to edit the pm_power_state_set() function to allow I.E. the SUSPEND_TO_RAM state instead of just the SOFT_OFF state.

    can you please show how to edit and what should be under this case SUSPEND_TO_RAM 

    switch (info.state) {
        case PM_STATE_SOFT_OFF:
            nrf_regulators_system_off(NRF_REGULATORS);
            break;
       
    case SUSPEND_TO_RAM :
           ???????????????????????
            break;
        default:
            LOG_DBG("Unsupported power state %u", info.state);
            break;
        }
Related