Arm Mbed OS support forum

NRF52 Hardware timers problem

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;

void timer_handler_read(nrf_timer_event_t event_type, void * p_context)
{
count0 = nrfx_timer_capture_get(&counter_timer, NRF_TIMER_CC_CHANNEL0);
}

void timer_counter_handler(nrf_timer_event_t event_type, void* p_context)
{

}

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);

}

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

Hi,

what version of Mbed OS are you using? If you are using Mbed 6 then ‘printf’ is not supported by default, you need to be using minimal_printf…

Regards
Anna

Hi, i’m using mbed os 6.2.1. I don’t see any problem with the printf function… but I will try to use minimal_printf. Anyway, if I comment all the printf statements the problem persist, the callback function (timer_handler_read) never is called. I think that the problem is that mbed change the IRQ vectors in same way, beacuse if I try this code without mbed in another compiler (SEGGER STUDIO) it works fine, the callback function is called.

Thanks