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

CPU not going to sleep because of TIMER2 interrupt

Hi,

the system we are using includes the nrf52832 SoC with an external ADC and en external crystal for HFCLK. running SoftDevice s132 v2 (based on SDK 11)

in our system we turn on the hfclk and ppi and TIMER2 to sample an external ADC in a cyclic manner. after sampling is done we go to sleep most of the time until next sampling cycle.
what I noticed is that sometimes randomly the CPU doesn't go to sleep after a sampling event and after the next sampling event it does go to sleep.
I checked which interrupt is pending that denies the WFE from entering sleep by checking for all interrupts using sd_nvic_GetPendingIRQ and I found that TIMER2 interrupt is pending when this issue happens.

 when we start the sampling process we do the following:

	uint32_t is_running = 0;
	sd_clock_hfclk_request();
	do {
		sd_clock_hfclk_is_running(&is_running);
	} while (!is_running);
	
	err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_gpiote_init();
	APP_ERROR_CHECK(err_code);
	
	APP_ERROR_CHECK(nrf_drv_timer_init(&sample_timer, NULL, sample_timer_event_handler));
	
	uint32_t compare_evt_addr;
    uint32_t gpiote_task_addr;
	nrf_ppi_channel_t ppi_channel;

	nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_HIGH;
	APP_ERROR_CHECK(nrf_drv_gpiote_out_init(CONV_START_GPIO_OFFSET, &config));
	
	uint32_t time_ticks = nrf_drv_timer_us_to_ticks(&sample_timer, time_to_sample);
	nrf_drv_timer_extended_compare(&sample_timer, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
	err_code = nrf_drv_ppi_channel_alloc(&ppi_channel);
    APP_ERROR_CHECK(err_code);

    compare_evt_addr = nrf_drv_timer_event_address_get(&sample_timer, NRF_TIMER_EVENT_COMPARE0);
    gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(CONV_START_GPIO_OFFSET);

    err_code = nrf_drv_ppi_channel_assign(ppi_channel, compare_evt_addr, gpiote_task_addr);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_enable(ppi_channel);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_out_task_enable(CONV_START_GPIO_OFFSET);

	//start sampling timer (trigger to starting the process)
	nrf_drv_timer_enable(&sample_timer);

when we finish sampling the following is done:

nrf_drv_timer_uninit(&sample_timer);
sd_clock_hfclk_release();
nrf_drv_ppi_uninit();
nrf_drv_gpiote_uninit();
augu_uninit_adc_spi();

if I change the uninit of all the peripherals as follows it solves the problem:

sd_clock_hfclk_release();
nrf_drv_ppi_uninit();
nrf_drv_timer_disable(&sample_timer);
nrf_drv_timer_uninit(&sample_timer);
nrf_drv_gpiote_uninit();
augu_uninit_adc_spi();

can somebody explain why this happens? should the timer be uninit after sd_clock_hfclk_release? and what is the proper way to uninit the timer?
 

  • I think the reason that this happened is because I used nrf_drv_timer_uninit without nrf_drv_timer_disable that is because the nrf_drv_timer_uninit function starts with 
    nrf_drv_common_irq_disable(nrf_drv_get_IRQn(p_instance->p_reg));

    and then disables the timer this can result in theory that the timer interrupt happens exactly after the nrf_drv_common_irq_disable was called and before nrf_drv_timer_disable that will result in a pending interrupt that denies the WFE from entering sleep mode.

Related