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

Counting edges with PPI and GPIOTE

I've used the example in examples/peripheral/gpiote to count edges of a WATCHDOG pin from a different MCU:

static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(4);
#define AMOUNT_OF_PULSES 0x1FFFFFFF

static void watchdog_timer_init()
{
    ret_code_t err_code;
    if (!nrfx_gpiote_is_init())
    {
        err_code = nrfx_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }

    nrfx_timer_config_t timer_cfg = {NRF_TIMER_FREQ_16MHz, NRF_TIMER_MODE_COUNTER, NRF_TIMER_BIT_WIDTH_32, NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, NULL};

    nrfx_timer_init(&m_timer, &timer_cfg, NULL);

    nrfx_timer_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, AMOUNT_OF_PULSES, false);

    nrfx_gpiote_in_config_t i_config = {NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIO_PIN_NOPULL, false, true};

    APP_ERROR_CHECK(nrfx_gpiote_in_init(IN_WATCHDOG_PIN, &i_config, NULL));
    nrfx_gpiote_in_event_enable(IN_WATCHDOG_PIN, true);

    #warning "Hack to enable SHORTS"
    m_timer.p_reg->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;

    err_code = nrf_drv_ppi_init();
    if (err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED)
    {
        APP_ERROR_CHECK(err_code);
    }

    nrf_ppi_channel_t ppi_channel_input;
    // Setup the GPIOTE input to trigger TASKS_COUNT
    nrfx_ppi_channel_alloc(&ppi_channel_input);
    nrfx_ppi_channel_assign(ppi_channel_input, nrfx_gpiote_in_event_addr_get(IN_WATCHDOG_PIN), nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_COUNT));
    nrfx_ppi_channel_enable(ppi_channel_input);

    nrfx_timer_enable(&m_timer);
}

After starting the timer I want to periodically get the current count value with:

toggle_count = nrfx_timer_capture_get(&m_timer, NRF_TIMER_CC_CHANNEL0);
NRF_LOG_INFO("COUNT %i", toggle_count);
return toggle_count;

But it always gives me a constant value. If I use a gpiote interrupt and increment a counter in the interrupt routine it runs fine which tells me that the pin

is working fine. But somehow the counter or PPI does not work as expected. So how can I make a counter count on a PIN toggle and get and reset the

count from within the main context.

Thanks in advance.

C.W.

Parents Reply
  • The gpiote interrupt is not enabled, only the event is enabled, i.e. last argument in nrf_drv_gpiote_in_event_enable(PIN_IN, false) is set to false.

    Same applies to the timer used for counting, the function nrf_drv_timer_compare_int_enable() and nrf_drv_timer_extended_compare() is not used to enable any interrupt for that timer.

    In the example, the m_timer_read interrupt is only used to periodically print the counter value.

    Also, the example I linked to does by default not put the CPU to sleep. Something like the snippet below should be added to main() while-loop in order to do that.

        if (NRF_LOG_PROCESS() == false)
        {
                            // Wait for an event.
            __WFE();
            // Clear the internal event register.
            __SEV();
            __WFE();
        }

Children
Related