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

rtc nrf51 SDK example matches COMPARE0 only once

In order to learn how to use the RTC0 to handle an event every second, I am debugging the rtc SDK example.

Expectation: The rtc example sets the time to check the counter time at 3 seconds. I expect every 3 seconds. the int_type in rtc_handler() will equal NRF_DRV_RTC_INT_COMPARE0.

What I am seeing: the int_type in rtc_handler() equals NRF_DRV_RTC_INT_COMPARE0 after the first three seconds. Then int_type equals only NRF_DRV_RTC_INT_TICK.

Question: is my assumption correct the COMPARE0 should keep repeating such that there is a match every 3 seconds (in this example)

Question: If not, what is the example missing to do so?

thank you.

  • Are you resetting the timer when you get the compare? If not it will just count all the way to the maximum count, then wrap around and start at zero and only when it gets to the same count again will you get the next COMPARE0. If you have the timer running fast that's 512 seconds, if you have it running as slowly as possible, that's 24 days before you'll see the next interrupt.

  • Thank you for your answer. I think I do... it seems i reset the count, but the compare0 event doesn't recur?

    /** @brief: Function for handling the RTC0 interrupts.
     * Triggered on TICK and COMPARE0 match.
     */
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
            nrf_drv_rtc_counter_clear(&rtc);
        }
        else if (int_type == NRF_DRV_RTC_INT_TICK)
        {
            nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
        }
    }
    
  • sadly, I already had :-).... my question then is one of usage. Please forgive this basic question however, I do not know the answer. What I cannot get working is calling the interrupt handler for COMPARE0 every 3 seconds. I.e.: it only gets called once. On further debugging, I thought the following would work. Why does it not work? Thank you.

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
            //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
            uint32_t err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME*RTC0_CONFIG_FREQUENCY,true);
            APP_ERROR_CHECK(err_code);
            //Power on RTC instance
            nrf_drv_rtc_disable(&rtc);
            nrf_drv_rtc_enable(&rtc);
        }
        else if (int_type == NRF_DRV_RTC_INT_TICK)
        {
            nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
        }
    }
    
  • Hi

    The internal event handler of the rtc driver, i.e. the nrf_drv_rtc_int_handler, handles the RTC0 peripheral interupt and then calls the registered event handler of the application. If you look into the nrf_drv_rtc_int_handler, you see that interrupts for any COMPARE[x] events are disabled, while TICK and OVERFLOW interrupts are not disabled. If you avoid disabling the COMPARE[x] interrupts, then the COMPARE[0] interrupt will be recurrent after you clear the RTC0 counter. The following code shows the modified nrf_drv_rtc_int_handler where two lines are commented out to enable recurrent COMPARE[x] interrupt:

    __STATIC_INLINE void nrf_drv_rtc_int_handler(NRF_RTC_Type * p_reg, uint32_t instance_id)
    {
    		uint32_t i;
    		uint32_t int_mask = (uint32_t)NRF_RTC_INT_COMPARE0_MASK;
    		nrf_rtc_event_t event = NRF_RTC_EVENT_COMPARE_0;
    
    		for (i = 0; i < RTC_CHANNEL_NUM; i++)
    		{
    				if (nrf_rtc_int_is_enabled(p_reg,int_mask) && nrf_rtc_event_pending(p_reg,event))
    				{
    						//nrf_rtc_event_disable(p_reg,int_mask);
    						//nrf_rtc_int_disable(p_reg,int_mask);
    						nrf_rtc_event_clear(p_reg,event);
    						m_handlers[instance_id]((nrf_drv_rtc_int_type_t)i);
    				}
    				int_mask <<= 1;
    				event    = (nrf_rtc_event_t)((uint32_t)event + sizeof(uint32_t));
    		}
    		event = NRF_RTC_EVENT_TICK;
    		if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_TICK_MASK) &&
    				nrf_rtc_event_pending(p_reg, event))
    		{
    				nrf_rtc_event_clear(p_reg, event);
    				m_handlers[instance_id](NRF_DRV_RTC_INT_TICK);
    		}
    
    		event = NRF_RTC_EVENT_OVERFLOW;
    		if (nrf_rtc_int_is_enabled(p_reg,NRF_RTC_INT_OVERFLOW_MASK) &&
    				nrf_rtc_event_pending(p_reg, event))
    		{
    				nrf_rtc_event_clear(p_reg,event);
    				m_handlers[instance_id](NRF_DRV_RTC_INT_OVERFLOW);
    		}
    }
    

    so with the above change to the nrf_drv_rtc and your proposed code of clearing the counter (as below code), it should work

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
    		if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    		{
    				nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
    				nrf_drv_rtc_counter_clear(&rtc);
    		}
    		else if (int_type == NRF_DRV_RTC_INT_TICK)
    		{
    				nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
    		}
    }
    
Related