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

Explicitly putting system in System ON and System OFF mode in a state machine

Board: nRF51-DK (nRF51422 chip)

SDK: 12.3.0

SoftDevice: S130

Compilation settings

  • Optimization level O1
  • Debug information generated

I have seen lot of nRF examples, however I choose to write my firmware as a finite state machine. So unlike nRF examples where main.c file contains everything, I have multifile project for helper functions, state machine action. In my main.c, I just loop between states.

I have states like

  • On Reset: I initialize minimum required peripherals such as logger, LFCLK, RTC, power management, GPIO. I also find the reset reason if system was reset due to wake up from SYSTEM OFF mode or due to hard reset etc. If my system was power cycled, I goto OFF state. If system had woken up from System OFF state, I move to next state called Hardware Init
  • Off: I enable interrupt on a button and put system in System OFF mode
  • Hardware Init: here I initialize BLE peripheral (GAPP, GATT, Advertise etc.) related functions and services. In addition I enable other required peripherals like TWI(I2C), SPI etc. for external components like Sensors, 
  • On: puts system in System ON (default low power mode)
  • Stream Sensor Data: I communicate with sensors using SPI/I2C
  • etc.

In every state I keep track of previous state, define state variables and depending upon values of state variables decide which state should be the next state. This way I loop from from one state to next. But I explicitly move in System ON and OFF states. 

However, when I measure current, it seems the current values are too high. So, I have some questions:

  1. What is the difference between NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF and NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF ? I see former is used for very low battery but what is difference ?
  2. I have switched logging ON and OFF in sdk_config.h but it seems not to change current reading during System OFF and ON mode. Whether debugging or otherwise, how to tell if my system is in System OFF mode or Emulated System OFF mode ?
  3. I have multiple GPIO pins which get interrupt signal from various sensors or from buttons to go into System ON/OFF mode. On some GPIO pins I have to separately detect HITOLO and LOTOHI transition in succession. I am using low accuracy for such GPIO pins for obvious reason to reduce power. Should I be using hi accuracy for some of these pins ? What is the functionality that low accuracy pins donot provide compared to high accuracy pins ?

Following are code snippets of my procedure I used to put system in ON or OFF mode is correct

typedef enum
{
  STATE_RESET = 0,
  STATE_ON,
  STATE_OFF,
  STATE_HW_INIT,
  STATE_BLE_CONNECT,
  STATE_STREAM_SENSOR_DATA,
  STATE_UNKNOWN 
} STATE_TYPE;

STATE_TYPE lastState = STATE_UNKNOWN;
STATE_TYPE currentState = STATE_UNKNOWN;
STATE_TYPE nextState = STATE_RESET;

bool volatile bWakeupFlag = false; // would be set to true say for example on timer expiry

static void system_sleep_off_mode(void)
{
  NRF_LOG_INFO("[%d] Entering System OFF sleep\r\n", order++);
  while (true)
  {
    if (false == NRF_LOG_PROCESS()) // required to process buffer if NRF_LOG_DEFERRED is set to 1
    {
      /* Blocking function call */
      nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }
  }
}

static void system_sleep_on_mode()
{
  NRF_LOG_INFO("[%d] Entering system on sleep\r\n", order++);
  NRF_LOG_FLUSH();
  
  while(false == bWakeupFlag)
  {
    /* Non-Blocking function call */
    nrf_pwr_mgmt_run();
  }
  
  NRF_LOG_INFO("[%d] Exiting system on sleep\r\n", order++);
}

STATE_TYPE state_action_off( void )
{
  currentState = nextState;
  system_sleep_off_mode();
  
  nextState = lastState;
  lastState = currentState;
  return nextState;     
}

STATE_TYPE state_action_on( void )
{
  currentState = nextState;
  system_sleep_on_mode();
  
  nextState = lastState;
  lastState = currentState;
  return nextState;   
}
  
int main(void)
{
  STATE_TYPE nextState = STATE_RESET;
  
  do
  {
    switch (nextState)
    {
      case STATE_RESET:
        nextState = state_action_reset();
        break;
      
      case STATE_ON:
        nextState = state_action_on();
        break;

      case STATE_OFF:
        nextState = state_action_off();
        break;

      case STATE_HW_INIT:
        nextState = state_action_hw_init();
        break;

      case STATE_BLE_CONNECT:
        nextState = state_action_ble_connect();
        break;

      case STATE_STREAM_SENSOR_DATA:
        nextState = state_action_stream_sensor_data();
        break;

      case STATE_UNKNOWN:
      default:  /* Incorrect state. Goto reset state */
        nextState = STATE_RESET;
        break;
    }
  } while(1);
}

Parents
  • 1. according to devzone: The difference between the two is that one schedules a callback to put the system to sleep, while the other does it directly

    2. Emulated system off will happen if the debugger is attached and you will get a current penalty of about ~1mA

    3. Are you asking about constant latency vs low power mode? if so, constant latency will give much higher current consumption.

Reply
  • 1. according to devzone: The difference between the two is that one schedules a callback to put the system to sleep, while the other does it directly

    2. Emulated system off will happen if the debugger is attached and you will get a current penalty of about ~1mA

    3. Are you asking about constant latency vs low power mode? if so, constant latency will give much higher current consumption.

Children
No Data
Related