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

RTC1 IRQ not firing until debugger connected.

We're using an nRF52832, SDK14.0.0, SoftDevice 132 v5.

Early in our firmware lifecycle, before SoftDevice is enabled, we configure our PMIC. This involves performing some TWI transactions and then setting a single-shot app_timer with an expiry of ~126msec.

Around 10% of the time, from a warm reset, the RTC1 IRQ is not firing, so the app_timer list is never walked, and our timer's callback is never called.

When operating nominally, the RTC1 IRQ is raised after almost exactly 126msec, and our callback is executed.

When we detect the failure scenario, we attach-and-halt in SEGGER's Ozone debugger. The value of r15 confirms that we're in WFE mode, and our call stack correctly shows us in our "sleep until an event" loop that's part of our PMIC configuration. At this point, if we single-step, we immediately end up in the RTC1_IRQHandler and the system proceeds as normal.

Our loop looks roughly like this:

bool check_pmic(pmic_t *pmic) {
  send_twi_request(pmic);

  app_timer_create(my_timer, pmic_app_timer_expired_callback, pmic);
  app_timer_start(my_timer, 126msec_in_tics);
  
  while (waiting_for_pmic(pmic)) {
    sleep_cpu();
    poll_pmic(pmic);
  }
}

void sleep_cpu(void) {
  uint32_t const fpscr = __get_FPSCR();                                       
  uint32_t const fpscr_off = fpscr & ~(uint32_t)VCE_CPU_FPSCR_EXCEPTION_BITS_MASK;                   

  __set_FPSCR(fpscr_off);                                                     
  __get_FPSCR();                                                              

  NVIC_ClearPendingIRQ(VCE_CPU_IRQ_FPU);                                      

  if (nrf_sdh_is_enabled()) {                                                 
    sd_app_evt_wait();                                                        
  } else {                                                                    
    __WFE();                                                                  
  }                                                                           
}

With the details of the pmic stuff left as pseudocode, but our cpu_sleep function copied verbatim (comments scrubbed).

One thing I noticed is that SoftDevice is disabled, so the code path is just __WFE. I see that sd_app_evt_wait() is just a __WFE anyway, and that no path does the SEV / WFE / WFE pattern.

Anyway, what would cause RTC1 IRQ to not raise until a debugger is attached and stepped? Similarly, using SEGGER's RTT protocol (which turns on SWO) to drain our firmware logs causes the RTC1 IRQ to raise.

Parents Reply Children
No Data
Related