NRF5340 power management

Hi Devzone,

I am using an nrf5340 with NCS v2.0.0 and am trying to implement power management.
I found this link and have been taking hints from it
https://github.com/nrfconnect/sdk-zephyr/tree/main/samples/boards/nrf/system_off

This is the scenario I would like to implement.

  1. Enter deep sleep mode (used primarily for shipping device and storage)
  2. Wakeup on GPIOTE interrupt when ready for use
  3. Advertise/pair/bond
  4. Do a few tasks based on timer
    1. Sample data from various devices attached to peripherals
  5. Setup to enter PM_STATE_SUSPEND_TO_RAM sleep mode
    1. Un-init peripherals
      1. Set peripherals to PM_DEVICE_ACTION_SUSPEND
      2. Set peripheral pins to output low
    2. Enter PM_STATE_SUSPEND_TO_RAM
  6. Wakeup on timer
    1. Init peripherals
      1. Set peripherals to PM_DEVICE_ACTION_RESUME
      2. Initialize peripherals
    2. Sample data from various devices attached to peripherals
  7. Got back to 5

Peripherals used:
I2C1
SPIM2
SPIM4
SAADC
DPPI

reduced prj.conf setup

CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_TMP116=y
CONFIG_NRFX_SPIM2=y
CONFIG_NRFX_SPIM4=y
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_NRFX_SAADC=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_DPPI=y

 To prevent the nrf5340 from entering deep sleep mode until I tell it I call

pm_policy_state_lock_get(PM_STATE_SOFT_OFF);
And to enter sleep SUSPEND_TO_RAM I call
    struct pm_state_info sleep_state = {PM_STATE_SUSPEND_TO_RAM, 0, 0};
    pm_state_force(0u, &sleep_state);

I have mostly everything mostly working, I can read and write to my devices on the various peripherals. The issue I am running into is directly setting the power setting of the various peripherals.

Calling this code to set the I2C1 device to suspend, results in a system crash.

struct device *i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c1));
pm_device_action_run(i2c_dev, PM_DEVICE_ACTION_SUSPEND);

After stepping through that code I see that the crash occurs after calling

atomic_test_bit(&pm->flags,
			       PM_DEVICE_FLAG_STATE_LOCKED);

I saw this same issue when setting the power state for SPI2.

I have a few questions:

  1. What devices are supported by pm_device_action_run? It runs OK in the sample for UART0 listed above but not for I2C1 or SPI2.
  2. Does the peripherals have to be un-initialized and the pins configured in output low mode for the greatest power saving?
  3. What is the correct order of operation for the peripherals:
    1. For wakeup? Set to active state, then initialize or vice versa?
    2. For sleep? Set to suspend then un-initialize or vice versa?
  4. Should I even bother trying to run a pm_device_action_run on the I2C1, SPIM2, etc... or will the power management set that for me automatically?
  5. I have a tmp117 attached to I2C1 and am using the zephyr driver to communicate with it. How do you unconfigure the I2C1? Again is it even necessary to configure it, use it then unconfigure it after use to achieve power savings?
  6. Do I need to setup power states in my overlay file? I didn't see one in the sample I sited above.
  7. What is the best way to achieve the scenario I described above with the best power savings?
  8. How do you set wake on interrupt for a single GPIOTE? The example has this for a GPIO sw0 on the nrf5340dk
    1. 	/* Configure to generate PORT event (wakeup) on button 1 press. */
      	nrf_gpio_cfg_input(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios),
      			   NRF_GPIO_PIN_PULLUP);
      	nrf_gpio_cfg_sense_set(NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(sw0), gpios),
      			       NRF_GPIO_PIN_SENSE_LOW);
      
    2. This is what I currently have for GPIOTE using pin31. Will this work the same way?
    3. #define GPIOTE31             NRF_GPIO_PIN_MAP(0,31)
      	            
      const nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
      nrfx_gpiote_in_init(GPIOTE31, &in_config, set_wakeup_detected);

Any help in configuring and setup to achieve best power saving would be appreciated. 

Thanks

Parents Reply
  •    

    I required the device should be run in low power mode when there is no work to do. so I gone through the state.h and found that there are different states. So I choose  PM_STATE_RUNTIME_IDLE or PM_STATE_SUSPEND_TO_IDLE so just curious like if I select one of them then on some event how to wakeup the device to a normal state.

    Also is there any best state other than PM_STATE_SOFT_OFF which help my device to save more power without losing its context?


    Do I just need to disable/suspend the resources that are taking more power, this will save the power consumption of the battery. CPU will automatically go into sleep mode?

    Can you please enlighten why there are different modes and When to use them? like, PM_STATE_RUNTIME_IDLE, PM_STATE_SUSPEND_TO_IDLE, PM_STATE_STANDBY and 

    PM_STATE_SUSPEND_TO_RAM.
    Also how to use them?
Children
No Data
Related