This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

M33 core in nRF9160 low power mode - Constant latency mode

Hello, I am working on low power modes of MCU M33 core in nRF9160 SOC.

From the document of nRF9160 product specification v1.0, understood that there are two low power modes for M33 core 

1. System ON Mode

     a. Low power mode - Default mode after reset

     b. Constant Latency mode.

2.System OFF Mode - The device is put into System OFF mode using the REGULATORS register interface.

As you suggested in my previous case Case ID: 246126, In serial Link monitor example code, I found enter_sleep() function which is actually System OFF Mode.

I have changed the enter_Sleep() function to enter into system ON mode instead of System OFF mode as in the example.

Below are my code which I am trying to wake up using GPIO button from system ON mode - low power mode but not successful.

When I checked the TASKS_LOWPWR register in embedded segger studio mode, the value in this register is still 0  though I am writing 1 to this register using nrf_power_task_trigger(NRF_POWER_NS,NRF_POWER_TASK_LOWPWR) API

I have also checked operation of the System ON mode - Constant Latency Mode, TASKS_CONSTLAT register is still 0.

void enter_sleep(void)
{

nrf_gpio_cfg_input(CONFIG_SLM_INTERFACE_PIN,
NRF_GPIO_PIN_PULLUP);
nrf_gpio_cfg_sense_set(CONFIG_SLM_INTERFACE_PIN,
NRF_GPIO_PIN_SENSE_LOW);


lte_lc_power_off();
bsd_shutdown();
nrf_power_task_trigger(NRF_POWER_NS,NRF_POWER_TASK_LOWPWR);

}

Can you guide me how to enable these modes- low power and contant latency mode.

  • Hi, I see you have logging enabled. It keeps the UART peripheral running and can take anywhere between 0.5 and 1.5 mA. I suggest disabling it and seeing where that leaves you. 

  • Hi Heidi,

    Yesterday I followed your suggestion and turned OFF logging feature and disable UART peripheral. Current consumption i was able to land is

    System ON Mode-Idle Mode : 2.93mA

    System OFF Mode - 5.42uA.

    Still not matching to datasheet values.

    Let me know if you need further details.

  • Hi, could I take a look at your code?

    Based on the values you're getting, it looks like the modem is still running when in System ON Mode. Is this intended? If yes, you will need to implement PSM or eDRX intervals to reduce power consumption. 

    Best regards,

    Heidi

  • Hi Heidi,

    Here I have attached by source file, in function sleepModeEnter(shutdown_modes_t modes) i have implemented Idle mode and SYSTEM OFF mode functions.

    I have disabled the Modem using AT+CFUN=0 in lte_lc_power_off function and also bsd shutdown.


    
    
    
    #include <drivers/gpio.h>
    #include <modem/lte_lc.h>
    #include <bsd.h>
    #include <hal/nrf_power.h>
    #include <hal/nrf_regulators.h>
    #include "Uarts.h"
    #include "TaskDefs.h"
    #include "Common.h"
    
    
    #define BUTTON_PORT  DT_GPIO_KEYS_BUTTON_2_GPIOS_CONTROLLER
    #define BUTTON_PIN   DT_GPIO_KEYS_SW0_GPIOS_PIN
    
    static struct gpio_callback wakeup_cb;
    static struct device *gpio_dev;
    taskAttributes_t taskAttributeTable[TOTAL_NUMBER_OF_TASKS];
    bool isReadyToSleep = false;
    extern uartDevice_t uartDevs[];
    extern const k_tid_t tid_EvcComm; 
    
    K_SEM_DEFINE(task_state, 1, 1); //Statically define and intialize a semaphore
    
    LOG_MODULE_REGISTER(CommonTask, CONFIG_CP_LOG_LEVEL);
    
    void t_CommonTask(void *p1, void *p2, void *p3)
    {
        ARG_UNUSED(p1);
        ARG_UNUSED(p2);
        ARG_UNUSED(p3);
        LOG_INF("Periodic Task started");
        for (;;)
        {
            MonitorTasksState();
    
            if (isReadyToSleep)
            {
                sleepModeEnter(SHUTDOWN_MODE_IDLE);
            }
        }
    }
    
    void sleepModeEnter(shutdown_modes_t modes)
    {
       wakeupSource_init();
       switch(modes)
       {
          case SHUTDOWN_MODE_IDLE:
        
          uartDeinitial(&uartDevs[EVC_UART_IDX],DEVICE_PM_OFF_STATE);
          lte_lc_power_off();
          bsd_shutdown();
    
          /* As suggested in ticket 
             https://devzone.nordicsemi.com/f/nordic-q-a/59812/m33-core-in-nrf9160-low-power-mode---constant-latency-mode
             to use Zephry Idle mode API.
          */
          k_cpu_idle();
    
          break;
    
          case SHUTDOWN_MODE_SLEEP:
    
              lte_lc_power_off();
              bsd_shutdown();
    //          sys_set_power_state(SYS_POWER_STATE_DEEP_SLEEP_1);
              nrf_regulators_system_off(NRF_REGULATORS_NS);
    
              break;
    
          default:
          break;
       }
    }
    
    void SleepModeExit(struct device *gpiob,u32_t pins)
    {
        gpio_pin_disable_callback(gpiob, pins);
        gpio_remove_callback(gpiob, &wakeup_cb);
        gpio_pin_configure(gpiob, pins, GPIO_DIR_IN | GPIO_PUD_NORMAL);
    }
    
    
    void wakeupSource_init(void)
    {
    
        int err;
    
        gpio_dev = device_get_binding(BUTTON_PORT);
        if (gpio_dev == NULL)
        {
            LOG_ERR("Error in GPIO binding: %d", err);
            return;
        }
        err = gpio_pin_configure(gpio_dev, BUTTON_PIN,
                GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL |
                GPIO_INT_ACTIVE_LOW | GPIO_PUD_PULL_UP |
                GPIO_INT_DEBOUNCE);
        if (err)
        {
            LOG_ERR("GPIO_0 config error: %d", err);
            return;
        }
        gpio_init_callback(&wakeup_cb,buttonPresscallback,BIT(BUTTON_PIN));
    
        err = gpio_add_callback(gpio_dev, &wakeup_cb);
        if (err)
        {
            LOG_ERR("GPIO_0 add callback error: %d", err);
            return;
        }
        err = gpio_pin_enable_callback(gpio_dev, BUTTON_PIN);
        if (err)
        {
            LOG_ERR("GPIO_0 enable callback error: %d", err);
        }
    }
    
    void buttonPresscallback(struct device *gpiob, struct gpio_callback *cb,u32_t pins)
    {
    
      SleepModeExit(gpiob,BUTTON_PIN); 
    }
    
    
    void updateTaskState(u8_t TaskNum , taskStates_t state)
    {
        if (taskAttributeTable[TaskNum].taskCurrentState != state)
        {
    
            k_sem_take(&task_state, K_FOREVER);
    
            taskAttributeTable[TaskNum].taskPreviousState = taskAttributeTable[TaskNum].taskCurrentState;
    
            taskAttributeTable[TaskNum].taskCurrentState = state;
    
            k_sem_give(&task_state);
        }
    }
    
    
    
    /*! \fn       void MonitorTasksState(void)
     *  \brief
     *  \details  This function monitors all tasks' state. If all the tasks are in sleep state
     *  \details  Put the system to sleep
     *  \param    void
     *  \return   void
     */
    void MonitorTasksState( void )
    {
        u8_t taskCounter = 0;
        bool allTasksInSleep = true;
    
    
        for(taskCounter = 1; taskCounter < TOTAL_NUMBER_OF_TASKS; taskCounter++)
        {
            if(taskAttributeTable[taskCounter].taskCurrentState != TASK_STATE_ASLEEP)
            {
                allTasksInSleep = false;
                break;
            }
        }
    
        if(allTasksInSleep == true)
        {
           isReadyToSleep = true;
        }
      
    }
    
    K_THREAD_DEFINE(tid_Common, COMMON_TASK_STACKSIZE, t_CommonTask, NULL, NULL, NULL, COMMON_TASK_PRIORITY, 0, K_NO_WAIT);

  • Do I also need to set application data profile in low power mode

    %XDATAPRFL=<power_level>

    0 – Ultra-low power

    1 – Low power

    2 – Normal

    3 – Performance

    4 – High performance

Related