WDT continues to run while in deep sleep mode.

My project utilizes the deep sleep or systemOff() function to minimize battery consumption. I'm at the final stages of development and I've run into some strange behavior. There are two occasions where we want the device to go to sleep. It is important to note that the sleep function called is the same in both circumstances:

Inactivity timer expires: After 30 seconds of no user activity the device should go to sleep. This works fine. A timer is used and my sleep function is called where important data is first saved to the last page in FLASH memory and then the device goes to sleep. When the device wakes up, it reads the saved data and runs with the saved parameters. No problem.

Critical battery alert: Here's where the problem lies. I have an analog pin connected to the battery with a lower voltage threshold programmed to set a "critical battery flag" if the voltage drops below it. If the critical battery flag is set the program runs the same sleep function as before and the device seems to go to sleep, accept that the WDT seems to be running. The device repeatedly resets, sees the battery is still low and goes to sleep only to wake right back up. I can increase the time it stays asleep by increasing the WDT time. Furthermore, once battery voltage is restored, the device wakes up as if the FLASH was empty/erased. If it was indeed shutting down successfully after the critical battery flag then it should have stored the data.

I found a post with a similar issue here. I'm not quite sure how to get PWR_MGMT_FPU_SLEEP_PREPARE to call from the main function, though, and nrf_pwr_mgmt_run() isn't working either. Any insight on how the WTD might wake up the system from deep sleep in one instance but not the other?

void sleep_system(void){

  uint32_t new_data [3] = {combination, ble_flags, battery_vthresh};  //  Backup important data.
  
  flash_erase(p_flash_adr_base);

  flash_write(p_flash_adr_base, new_data);

  //pwr_mgmt_fpu_sleep_prepare();
  //PWR_MGMT_FPU_SLEEP_PREPARE();
  nrf_pwr_mgmt_run();

  nrf_delay_ms(100);  //  Make sure backup is complete before running systemOff() as it will reset the MCU and erase RAM memory.

  systemOff();

}




uint32_t flash_read(uint32_t * adr){

  NRF_LOG_INFO("Reading from FLASH memory...");

  NRF_LOG_INFO("Data: %x at address: %x", *adr, adr);

  return *adr;

}




void flash_erase(uint32_t * adr){

  uint32_t err_code;
  uint32_t evt = 0;

  NRF_LOG_INFO("Erasing last page in FLASH memory...");
  NRF_LOG_INFO("Page #: %x", flash_page);


  err_code = sd_flash_page_erase(flash_page);

  APP_ERROR_CHECK(err_code);

  while(!evt){

    sd_evt_get(&evt);

  }
  if(evt == NRF_EVT_FLASH_OPERATION_ERROR){

    NRF_LOG_INFO("Error erasing FLASH.");
    return;

  }

  if(evt == NRF_EVT_FLASH_OPERATION_SUCCESS){

    NRF_LOG_INFO("FLASH page erased.");
    return;

  }
}




void flash_write(uint32_t * adr, uint32_t * new_data){

  uint32_t err_code;
  uint32_t evt = 0;

  NRF_LOG_INFO("Writing to FLASH memory...");

  err_code = sd_flash_write(adr, new_data, sizeof(new_data));
  APP_ERROR_CHECK(err_code);

  while(!evt){

    sd_evt_get(&evt);

  }
  if(evt == NRF_EVT_FLASH_OPERATION_ERROR){

    NRF_LOG_INFO("Error writing to FLASH.");
    return;

  }

  if(evt == NRF_EVT_FLASH_OPERATION_SUCCESS){

    NRF_LOG_INFO("Success writing to FLASH.");
    return;

  }
}




Parents
  • I guess I should mention the WDT specifics. I've set up the WDT to pause during sleep and halt. Here's the setup for it:

    void setup_wdt(void){
    
      uint32_t err_code = NRF_SUCCESS;
    
      nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
      config.reload_value = wdt_time;
      config.behaviour = NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT;
    
      err_code = nrf_drv_wdt_init(&config, wdt_evt_handler);
      APP_ERROR_CHECK(err_code);
      
      err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
      APP_ERROR_CHECK(err_code);
      
      nrf_drv_wdt_enable();
    
      nrf_delay_ms(100);
    
    }
    

  • I think I narrowed it down a bit.

    I removed the WDT and I'm still getting the same results. I did notice that none of the timers are getting shut off during the issue; my LED is controlled by a timer and it continues to blink when the program sleeps due to a critical battery flag but not during sleep triggered from the inactivity timer. The only difference I can see is that my sleep function is being called in the main loop for a critical battery but it's being called inside the event handler of the inactivity timer. Is there something that's going on inside the timer interrupt that is allowing proper operation that I can include in the main loop?

Reply
  • I think I narrowed it down a bit.

    I removed the WDT and I'm still getting the same results. I did notice that none of the timers are getting shut off during the issue; my LED is controlled by a timer and it continues to blink when the program sleeps due to a critical battery flag but not during sleep triggered from the inactivity timer. The only difference I can see is that my sleep function is being called in the main loop for a critical battery but it's being called inside the event handler of the inactivity timer. Is there something that's going on inside the timer interrupt that is allowing proper operation that I can include in the main loop?

Children
Related