RTC usage on Zephyr Issues

Hello,

I'm trying to run a simple example setting the RTC1 in a nRF52840-DK, but I'm having some issues.

Here is my prj,conf and code:

# nothing here
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_NRFX_RTC1=y

#include <zephyr/kernel.h>
#include <nrfx_rtc.h>
#include <nrfx_timer.h>

#define RTC_INSTANCE 1
#define ALARM_PERIOD_SECONDS  2
static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(RTC_INSTANCE);


void rtc_event_handler(nrfx_rtc_int_type_t int_type)
{
    if (int_type == NRFX_RTC_INT_COMPARE0) {
        // Handle RTC event here
        printk("RTC event occurred\n");
    }
}

void main(void)
{
    printk("Hello World!\n");

    nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
	config.prescaler = RTC_FREQ_TO_PRESCALER(1);
    nrfx_rtc_init(&rtc, &config, rtc_event_handler);
    nrfx_rtc_tick_enable(&rtc, true);
	
	uint32_t alarm_ticks = ALARM_PERIOD_SECONDS;
	nrfx_rtc_cc_set(&rtc, 0, alarm_ticks, true);
    nrfx_rtc_enable(&rtc);
}

The idea above is set the prescaler to 1 second and fire at every 2 seconds.

The RTC handler is simply not firing, as follows:

Can you help me to figure out what is missing? Code attached.

rtc_sleep.zip

  • Hi,

    You need to connect the interrupt from Zephyr's interrupt handling to the nrfx_rtc driver in your application for the interrupts to work correctly. Eg.:

    IRQ_CONNECT(DT_IRQN(DT_NODELABEL(rtc1)),
    DT_IRQ(DT_NODELABEL(rtc1), priority),
    nrfx_isr, nrfx_rtc_1_irq_handler, 0);

    Best regards,
    Jørgen

  • Hi Jorgen, 

    Thanks for the quick reply.

    With your MACRO I was able to get interrupts, but only for NRFX_RTC_INT_TICK and not NRFX_RTC_INT_COMPARE0.

  • I was able to get it running with the following code:

    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <nrfx_rtc.h>
    #include <nrfx_timer.h>
    
    #define RTC_INSTANCE 2
    #define CC_CHANNEL 0
    #define RTC_TIMEOUT_MS 5000
    #define RTC_PRESCALER_MS 125
    
    static nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(RTC_INSTANCE);
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
    
    void rtc_event_handler(nrfx_rtc_int_type_t int_type)
    {
    	switch(int_type) {
    		case NRFX_RTC_INT_COMPARE0:
    			printk("RTC compare event occurred\n");
    			gpio_pin_toggle_dt(&led);
    			nrfx_rtc_counter_clear(&rtc);
            	nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true);
    			break;
    		default:
    			break;
    	}
    }
    
    void main(void)
    {
        printk("Hello World!\n");
    
        nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
    	config.prescaler = RTC_FREQ_TO_PRESCALER(1000 / RTC_PRESCALER_MS);
    	
        nrfx_rtc_init(&rtc, &config, rtc_event_handler);
    
    	IRQ_CONNECT(DT_IRQN(DT_NODELABEL(rtc2)),
    			DT_IRQ(DT_NODELABEL(rtc2), priority),
    			nrfx_isr, nrfx_rtc_2_irq_handler, 0);
    	irq_enable(DT_IRQN(DT_NODELABEL(rtc2)));			
    
    	if (!device_is_ready(led.port)) {
            return;
        }
    
        if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) {
            return;
        }
    
     	nrfx_rtc_tick_disable(&rtc);
        nrfx_rtc_counter_clear(&rtc);
        nrfx_rtc_enable(&rtc);
        nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true);
    }

    My followup question here is the following:

    I'm toggling a led based on the RTC alarm.

    If I set my defines as: 

    #define RTC_TIMEOUT_MS 5000
    #define RTC_PRESCALER_MS 125

    And set my prescaler and cc timer as:

    config.prescaler = RTC_FREQ_TO_PRESCALER(1000 / RTC_PRESCALER_MS);
    
    nrfx_rtc_cc_set(&rtc, CC_CHANNEL, RTC_TIMEOUT_MS / RTC_PRESCALER_MS, true);

    I get the expected toggle ratio defined at RTC_TIMEOUT_MS (5 seconds).

    If I change the RTC_PRESCALER_MS to a larger value, like 500 ms, I get my toogle ratio 4x faster (1.25 seconds), and not the same as I expected.

  • The RTC prescaler can take a value between 0 and 4095, this means that the minimum frequency of the RTC is 32768/4096=8. If you set RTC_PRESCALER_MS to 500, your input to RTC_FREQ_TO_PRESCALER() will be 2, which is below the minimum frequency. The prescaler will then likely be set to the maximum value of 4095, which map well to the 4x ratio you are seeing on the interrupts.

Related