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

How to check for pending interrupts before calling sd_app_evt_wait?

Hi. I am having trouble getting the sd_app_evt_wait() call to work correctly in my code. My main program works like this:

<inits>
for(;;)
{
   <read saadc>
   <sd_app_evt_wait> // app_timer should make this return in 10 seconds
}

I have an app_timer that causes sd_app_evt_wait to return by firing every 10 seconds. The problem is, after sampling the ADCs, the call to sd_app_evt_wait returns immediately, running the loop forever. It doesn't sleep and wait for the timer. If I put a second call to sd_app_evt_wait directly after the first, the first call returns, and the second call sleeps until the timer wakes it (desired operation, but with two calls). From what I have learned of the sd_app_evt_wait function, if there are pending interrupts, it will immediately return. However, if I read the NVIC->ISPR at any time, it is 0. No interrupts pending, but sd_app_evt_wait returns once, then sleeps properly, on the Second call. I read about the FPU interrupts, so I added the following:

 uint32_t FPU_EXCEPTION_MASK = 0x0000009F;
pending = __get_FPSCR();
if (pending)
{
	NRF_LOG_DEBUG("FPU Exceptions: %d\r\n", pending);
	/* Clear exceptions and PendingIRQ from the FPU unit */
	__set_FPSCR(__get_FPSCR() & ~(FPU_EXCEPTION_MASK));
	(void) __get_FPSCR();
	NVIC_ClearPendingIRQ(FPU_IRQn);
}

but they don't help. The variable "pending" is always 0, and the ISPR is always 0. Adding

NVIC_ClearPendingIRQ(SAADC_IRQn);
NVIC_ClearPendingIRQ(FPU_IRQn);

before the first call to sd_app_evt_wait doesn't help either. What am I missing?

  • I think your last comment might be trunkated. When you call sd_app_evt_wait we basically clear the event flags and go to sleep. This is described here. So there must be an event that is wakeing you up that we are probably missing. Are you sure you are checking alle tha SAADC events?

  • Comment edited.The printout in the ADC callback only fires once, on calibration complete. I print on any event in that handler, and am not seeing any other events. Is there any way an interrupt is not calling the handler or something?

  • You wouldn't happen to be using blocking mode by any chance? e.g. maybe your problem is related to this case. i.e. Event started isn't cleared and will wake the chip up again the first time you call sd_app_evt_wait?

  • Thanks for the link again. That looked promising but didn't work either. here is my ADC poll, with event clearing after measuring all channels. My FW still wakes after first SD_app_evt_wait.

    		for (uint8_t i = 0; i < saadc_channel_count; i++)
    	{
    		if (nrf_drv_saadc_channel_init(i, &channel_config[i]) != NRF_SUCCESS)
    		{
    			setFault(SAADC_FAULT);
    		}
    		if (nrf_drv_saadc_sample_convert(i, &results[i]) != NRF_SUCCESS)
    		{
    			setFault(SAADC_FAULT);
    		}
    		if (nrf_drv_saadc_channel_uninit(i) != NRF_SUCCESS)
    		{
    			setFault(SAADC_FAULT);
    		}
    		//	NRF_LOG_DEBUG("Measured channel %d, value was %d\n", m_adc_channel_enabled,
    		//					results[m_adc_channel_enabled]);
    	}
    	// fix for SD waking up again after sleeping, after the above measurements: clear events.
    	nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
    	nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
    

    setFault is my logger.

  • Could you try using the SAADC driver files found in SDK 13? There are some issues related to clearing of events in SDK 12 that can cause the device to wakeup. You may have to do some small changes in the files to get it working in SDK 12.1:

    • Change #if NRF_MODULE_ENABLED(SAADC) to #if SAADC_ENABLED
    • Change #include "sdk_common.h" to #include "sdk_config.h" and #include "nordic_common.h"
    • Comment out all NRF_LOG related calls.
Related