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

Can't get RTC to work with __RFE() but can make it work with __RFI()

I can make the RTC work with interrupts and __WFI().  I absolutely can't get events and __RFE() to work for the RTC.  However, it works if I replace the __RFE() with __NOP(), so the RTC and events *seem* to be configured properly.

I've just got to be missing something stupidly obvious.  Any help would be appreciated.

Thanks.

Code included which works on a nrf52832 (PCA10040 board):

#include <stdbool.h>
#include <stdint.h>

// $SDK/modules/nrfx
#include "mdk/nrf52_bitfields.h"

#include "hal/nrf_gpio.h"
#include "hal/nrf_clock.h"
#include "hal/nrf_rtc.h"


#include "delay/nrf_delay.h"


#define PIN_LED 19 // LED1

static unsigned irq_counter = 0;



#define RTC_USE_IRQ 0
#define RTC_USE_EVENT 1


#if RTC_USE_IRQ

void RTC0_IRQHandler(void) {
    nrf_rtc_event_clear(NRF_RTC0,NRF_RTC_EVENT_TICK);
    irq_counter++;
    // every 8 IRQs, we toggle the led -> 1Hz rate
    if(irq_counter %8 == 0) nrf_gpio_pin_toggle(PIN_LED);
}

int main(void)  // THIS VERSION WORKS FINE
{
    nrf_gpio_cfg_output(PIN_LED);
    nrf_gpio_pin_set(PIN_LED); // LED is off


    // Irq setup
    NVIC_SetPriority(RTC0_IRQn, 15); // Lowes priority
    NVIC_ClearPendingIRQ(RTC0_IRQn);
    NVIC_EnableIRQ(RTC0_IRQn);

    // Start LFCLK clock
    nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_RC); // 32KHz RC
    nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);


    // Set prescaler to the max value (12-bit)
    // -> 8Hz counter frequency
    nrf_rtc_prescaler_set(NRF_RTC0,(1<<12) -1);
    nrf_rtc_event_enable(NRF_RTC0, NRF_RTC_INT_TICK_MASK); /* yes INT mask must be used here */
    nrf_rtc_int_enable(NRF_RTC0,NRF_RTC_INT_TICK_MASK);
    nrf_rtc_task_trigger(NRF_RTC0,NRF_RTC_TASK_START);

    while(1) {
        __WFI();
    };
}
#endif

#if RTC_USE_EVENT

int main(void)  // THIS VERSION FAILS
{
    nrf_gpio_cfg_output(PIN_LED);
    nrf_gpio_pin_set(PIN_LED); // LED is off

    // Start LFCLK clock
    nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_RC); // 32KHz RC
    nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);

    // Set prescaler to the max value (12-bit)
    // -> 8Hz counter frequency
    nrf_rtc_prescaler_set(NRF_RTC0,(1<<12) -1);
    nrf_rtc_event_enable(NRF_RTC0, NRF_RTC_INT_TICK_MASK); /* yes INT mask must be used here */
    nrf_rtc_task_trigger(NRF_RTC0,NRF_RTC_TASK_START);

    while(1) {
        if (nrf_rtc_event_pending(NRF_RTC0, NRF_RTC_EVENT_TICK)) {  // __WFE could be a NOP()--so you have to check
            nrf_rtc_event_clear(NRF_RTC0,NRF_RTC_EVENT_TICK);
            irq_counter++;
            // every 8 IRQs, we toggle the led -> 1Hz rate
            if(irq_counter %8 == 0) nrf_gpio_pin_toggle(PIN_LED);
        }

        __WFE();  // If you replace this with __NOP() things work fine--so events are triggering
    };
}

#endif

Parents Reply Children
  • Ah, so I have to use the interrupt.  Okay, good to know.

    Then, this begs a followup question:  If the default should be interrupt handler and __WFI(), for which units and under what circumstance would you use WFE__() without an interrupt handler?

    When I used the DevZone search, I didn't come up with the thread you referred me to.  However, on Google, the keywords "site:nordicsemi.com nrf52832 wake up __WFE RTC" coughs up that thread as the second answer.  My apologies for not doing my homework.  I'll make sure to always use a specific Google search on the Nordic site from now on.

    Thanks for the help.

  • It's easier to find relevant to find relevant threads when you know they exists:) And it is sometimes it's better to search the forum with Google.I usually do both when looking for a particular case. Anyway, for a summary of the difference between __WFE and __WFI I would actually like to refer you to this answer by Anders here: https://devzone.nordicsemi.com/f/nordic-q-a/490/how-do-you-put-the-nrf51822-chip-to-sleep/2571#2571. It's an old answer covering the behavior on the nRF51s ARM Cortex M0 CPU, but the principle is the same for the cortex M4 used in the nRF52 series. As you can see, the main difference between these two instructions is that __WFE enters sleep conditionally unlike __WFI and thus making it better suited for spinlock loops. They can often be used interchangeably.

Related