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

Glitches when toggling pin with RTC + PPI + GPIOTE and reading RTC's COUNTER

When setting up a pin to toggle on the RTC's TICK event through the PPI and constantly reading the RTC's COUNTER on the nRF52832, my team observed frequent glitches on the pin signal. Here's a screenshot from our digital oscilloscope:

When not reading the RTC's COUNTER, we do not observe a single glitch.

Here's the code we used:

#include <stdbool.h>
#include <stdint.h>
#include "nrf_gpiote.h"
#include "nrf_drv_ppi.h"
#include "nrfx_gpiote.h"
#include "nrfx_rtc.h"
#include "nrfx_clock.h"
#include "app_error.h"

#define GPIO_OUTPUT_PIN_NUMBER 31

// RTC1 instance
static const nrfx_rtc_t m_rtc = NRFX_RTC_INSTANCE(1); 

// Dummy handlers
static void rtc_dummy_handler(nrfx_rtc_int_type_t int_type) {}
static void clock_dummy_handler(nrfx_clock_evt_type_t event) {}

static void rtc_init(void)
{
    nrfx_err_t err_code;

    // Start the internal LFCLK XTAL oscillator.
    err_code = nrfx_clock_init(clock_dummy_handler);
    APP_ERROR_CHECK(err_code);
    nrf_clock_lf_src_set(NRF_CLOCK_LFCLK_Xtal);
    nrfx_clock_lfclk_start();

    // Initialize RTC instance
    nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
    err_code = nrfx_rtc_init(&m_rtc, &config, rtc_dummy_handler);
    APP_ERROR_CHECK(err_code);

    // Enable tick event, disable interrupt
    nrfx_rtc_tick_enable(&m_rtc, false);
}

/**
 * @brief Setup PPI channel with event from RTC compare and task GPIOTE pin toggle.
 */
static void blinking_setup()
{
    nrfx_err_t err_code;

    nrfx_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    err_code = nrfx_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER, &config);
    APP_ERROR_CHECK(err_code);

    nrf_ppi_channel_t ppi_channel;
    err_code = nrfx_ppi_channel_alloc(&ppi_channel);
    APP_ERROR_CHECK(err_code);

    uint32_t rtc_tick_evt_addr = nrfx_rtc_event_address_get(&m_rtc, NRF_RTC_EVENT_TICK);
    uint32_t gpiote_task_addr = nrfx_gpiote_out_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);

    err_code = nrfx_ppi_channel_assign(ppi_channel, rtc_tick_evt_addr, gpiote_task_addr);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(ppi_channel);
    APP_ERROR_CHECK(err_code);

    nrfx_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER);
}

int main(void)
{
    uint32_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_gpiote_init();
    APP_ERROR_CHECK(err_code);

    // RTC init
    rtc_init();

    // Set up PPI channel with event from RTC compare and task GPIOTE pin toggle.
    blinking_setup();

    // Power on RTC instance
    nrfx_rtc_enable(&m_rtc);

    uint32_t counter;
    while (true)
    {
        // Comment this line to fix glitch
        counter = nrfx_rtc_counter_get(&m_rtc);
    }
}

We are testing this on PCA10040, version 1.2.4, which has an nRF52 marked QFAAE0. We are using SDK 16.0, no SoftDevice and GCC with O0.

I looked at the nRF52832 errata but didn't see anything that would explain this. It looks like a hardware bug to me, but I've been wrong before. Is that the case?

We were hoping to do some fairly precise timings with the RTC and I am now worried that reading the RTC's COUNTER may affect its reliability for timekeeping by causing it to jump ahead or skip cycles.

Parents Reply Children
No Data
Related