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

NRFX driver interrupt freeze the MCU

Hi!

I want to develop a simple program which count pulses in a digital pin in an interval of 10ms. I want to use a timer as a counter to count the pulses, also I want to use another counter to read the amount of pulses that occurs in the pin and reset the first counter.

I'm using MBED STUDIO with the nrf52-dk and the SDK15.0 (which is the default in mbed studio). The counter works well, but the second one doesn't. When I enable the interrupts, that I want use to read the value of the counter, the MCU freeze and never execute the interrupt.

Here is my code:

#include "nrf.h"
#include "nrfx_timer.h"
#include "mbed.h"
#include "app_error.h"
#include "nrfx_clock.h"
#include "nrfx_ppi.h"
#include "nrfx_gpiote.h"

#define TIMEOUT_MS 10
#define INPUT_PIN  P0_4 

DigitalOut led1(LED1);
DigitalOut led2(LED2, true);

volatile uint32_t count0 = 0;

const nrfx_timer_t counter_timer = NRFX_TIMER_INSTANCE(3);
const nrfx_timer_t timeout_timer = NRFX_TIMER_INSTANCE(4);

nrf_ppi_channel_t ppi_channel1;
nrf_ppi_channel_t ppi_channel2;

/**
 * @brief Handler for timer events.
 */
void timer_handler_read(nrf_timer_event_t event_type, void * p_context)
{
    count0 = nrfx_timer_capture_get(&counter_timer, NRF_TIMER_CC_CHANNEL0);
}

/**
 * @brief Handler for counter events.
 */
void timer_counter_handler(nrf_timer_event_t event_type, void* p_context)
{

}

/**
 * @brief Handler forin pin.
 */
static void in_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{

}


void gpiote_init()
{
    uint32_t err_code = NRF_SUCCESS;
    if(!nrfx_gpiote_is_init())
    {
        err_code = nrfx_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }

    nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrfx_gpiote_in_init(INPUT_PIN, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrfx_gpiote_in_event_enable(INPUT_PIN, false);
}

void timer_init()
{
    uint32_t err_code = NRF_SUCCESS;
    //Configure the timer
    nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    timer_cfg.mode = NRF_TIMER_MODE_TIMER;
    timer_cfg.frequency = NRF_TIMER_FREQ_16MHz;
    
    err_code = nrfx_timer_init(&timeout_timer, &timer_cfg, timer_handler_read);
    APP_ERROR_CHECK(err_code);
    printf("2 Error code: %d\n\r", err_code);

    uint32_t time_ticks = nrfx_timer_ms_to_ticks(&timeout_timer, TIMEOUT_MS);
    printf("Ticks: %d\n\r", time_ticks);
    nrfx_timer_extended_compare(&timeout_timer, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrfx_timer_enable(&timeout_timer);
    
    //Configure TIMER for counting of low to high events on GPIO
    nrfx_timer_config_t counter_cfg = NRFX_TIMER_DEFAULT_CONFIG;
    counter_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    counter_cfg.mode = NRF_TIMER_MODE_COUNTER;

    err_code = nrfx_timer_init(&counter_timer, &counter_cfg, timer_counter_handler);
    APP_ERROR_CHECK(err_code);

    nrfx_timer_enable(&counter_timer);
    
    printf("1 Error code: %d\n\r", err_code);

}

void ppi_init()
{
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrfx_ppi_channel_alloc(&ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrfx_ppi_channel_alloc(&ppi_channel2);
    APP_ERROR_CHECK(err_code);
    
    uint32_t gpiote_evt_addr_1 = nrfx_gpiote_in_event_addr_get(INPUT_PIN);
    uint32_t timer_count_count_task_addr = nrfx_timer_task_address_get(&counter_timer, NRF_TIMER_TASK_COUNT);
    
    uint32_t timer_count_capture_task_addr = nrfx_timer_task_address_get(&counter_timer, NRF_TIMER_TASK_CAPTURE0);
    uint32_t timer_count_clear_task_addr = nrfx_timer_task_address_get(&counter_timer, NRF_TIMER_TASK_CLEAR);
    uint32_t timer_timeout_compare_event_addr = nrfx_timer_event_address_get(&timeout_timer, NRF_TIMER_EVENT_COMPARE0);

    err_code = nrfx_ppi_channel_assign(ppi_channel1, gpiote_evt_addr_1, timer_count_count_task_addr);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_assign(ppi_channel2, timer_timeout_compare_event_addr, timer_count_capture_task_addr); // Capture counter timer using PPI to make sure this is not delayed by BLE interrupt
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_fork_assign(ppi_channel2, timer_count_clear_task_addr); // Clear counter timer using PPI to make sure this is not delayed by BLE interrupt
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_ppi_channel_enable(ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrfx_ppi_channel_enable(ppi_channel2);
    APP_ERROR_CHECK(err_code);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    if (!nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY))
    {
        nrfx_clock_hfclk_start();
    }

    //Configure in pin
    gpiote_init();

    //Configure the timmers
    timer_init();

    //Configure the PPI
    ppi_init();

    while (1)
    {
        led1 = !led1;
        ThisThread::sleep_for(200ms);
        printf("Counts 0: %d\n\r", count0);
    }
}

Thanks

Related