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

NRF51 RTC bug if event and interrupt are defined but not CC

Dear Nordic Support Team,

Defining NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE3_Msk; and NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE3_Msk; without specifing NRF_RTC1->CC[3] and NRF_RTC1->EVENTS_COMPARE[3] handler management resulting by freezing the nRF51822 after a complete RTC tick round : 512 seconds.

The current consumption rises to a stable 4mA and nothing no longer response (GPIOTE, RTC, WFI, ...). Chip is dead unitl next reboot, even watch dog doesn't response.

It takes me some times to find this problem out. Therefore I publish for the records. I there some guys from Nordic to confirm this behavior or it is a nRF51 RTC bug?

BTW, the CC[0] is highly used in this code, so this problem doesn't occurred when nothing happend to RTC1.

/**@brief 
 * Function for initializing the RTC1 counter.
 */
static void rtc1_init()
{	
    NRF_RTC1->PRESCALER = APP_TIMER_PRESCALER;
    NVIC_SetPriority(RTC1_IRQn, APP_IRQ_PRIORITY_LOW);
      
    NVIC_ClearPendingIRQ(RTC1_IRQn);
    NVIC_EnableIRQ(RTC1_IRQn);

	// Configure timer for clock
	NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE3_Msk;
	NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE3_Msk;
	 
    //NRF_RTC1->CC[3] = TICKS_1_SEC;	  //If not defined, the chip will freeze in 512 seconds
	
    NRF_RTC1->TASKS_START = 1;
    nrf_delay_us(MAX_RTC_TASKS_DELAY);  
}

/**@brief Function for handling the RTC1 interrupt.
 *
 */
void RTC1_IRQHandler(void)
{
    if (NRF_RTC1->EVENTS_COMPARE[0] != 0)
    {
        NRF_RTC1->EVENTS_COMPARE[0] = 0;
        NRF_RTC1->CC[0] += TIMER_INTERVAL;

        kernel_setSignal(SIGNAL_64HZ);			
    }
    		
    /*
	if(NRF_RTC1->EVENTS_COMPARE[3] != 0)
	{
		NRF_RTC1->EVENTS_COMPARE[3] = 0;
					
		//Watch Dog
		NRF_WDT->RR[0] = WDT_RR_RR_Reload;
					
		NRF_RTC1->CC[3] += TICKS_1_SEC;
		
       increment_time();			
	   kernel_setSignal(SIGNAL_1HZ);					
	}
   */
}
  • working just fine.

    tested with below code on PCA10028

    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    
    #define LEDS_NUMBER    3    
    #define LEDS_LIST { LED_1, LED_2, LED_3 }
    const uint8_t leds_list[LEDS_NUMBER] = LEDS_LIST;
    #define APP_TIMER_PRESCALER     0  
    #define APP_IRQ_PRIORITY_LOW  3
    #define TIMER_INTERVAL  0xFF
    
    
    /**@brief 
     * Function for initializing the RTC1 counter.
     */
    static void rtc1_init()
    {   
        NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
        NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_LFCLKSTART    = 1;
    
        while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
        {
            // Do nothing.
        }
        
        NRF_RTC1->PRESCALER = APP_TIMER_PRESCALER;
        NVIC_SetPriority(RTC1_IRQn, APP_IRQ_PRIORITY_LOW);
    
        NVIC_ClearPendingIRQ(RTC1_IRQn);
        NVIC_EnableIRQ(RTC1_IRQn);
    
        // Configure timer for clock
        NRF_RTC1->EVENTS_COMPARE[0] = 0;
        NRF_RTC1->CC[0] = 0XF;
        NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
        NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
        
        NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE3_Msk;
        NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE3_Msk;
    
        //NRF_RTC1->CC[3] = 0XFF;      //If not defined, the chip will freeze in 512 seconds
    
        NRF_RTC1->TASKS_START = 1;
        nrf_delay_us(50);  
    }
    
    /**@brief Function for handling the RTC1 interrupt.
     *
     */
    void RTC1_IRQHandler(void)
    {
        if (NRF_RTC1->EVENTS_COMPARE[0] != 0)
        {
            NRF_RTC1->EVENTS_COMPARE[0] = 0;
            NRF_RTC1->CC[0] += TIMER_INTERVAL;
        }
    
        if (NRF_RTC1->EVENTS_COMPARE[3] != 0)
        {
            NRF_RTC1->EVENTS_COMPARE[3] = 0;
            LEDS_INVERT(1 << LED_4);
        }
    
        
        /*
        if(NRF_RTC1->EVENTS_COMPARE[3] != 0)
        {
            NRF_RTC1->EVENTS_COMPARE[3] = 0;
    
            //Watch Dog
            NRF_WDT->RR[0] = WDT_RR_RR_Reload;
    
            NRF_RTC1->CC[3] += TICKS_1_SEC;
    
           increment_time();            
           kernel_setSignal(SIGNAL_1HZ);                    
        }
       */
    }
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        // Configure LED-pins as outputs.
        LEDS_CONFIGURE(LEDS_MASK);
    
        rtc1_init();
        while (true)
        {
            for (int i = 0; i < LEDS_NUMBER; i++)
            {
                LEDS_INVERT(1 << leds_list[i]);
                nrf_delay_ms(500);
            }
        }
    }
    
  • Even if you comment :

    if (NRF_RTC1->EVENTS_COMPARE[3] != 0)
        {
            NRF_RTC1->EVENTS_COMPARE[3] = 0;
            LEDS_INVERT(1 << LED_4);
        }
    
  • if you comment this, then the interrupt handler will be triggered immediately after it exits, because the system will think it is a new event that happened after its ISR was called. maybe this is what you mean by system being non responsive. This is because RTC1 ISR being called infinetely and not allowing anything else to execute.. It is important to the clear the event to correctly detect the next one.

  • Thanks for your explanation Aryan. I know that it is nonsense to do that, I just forgot to remove the lines to set event and interrupt in my code. But this problem was pretty hard to figure out because everything is working normally for 8 minutes, then boom.

Related