Avoiding Boron timer conflicts

Which of the nrf52840 hardware timers does DeviceOS use?

I want to use a timer for a precisely timed interrupt, but I don’t want to conflict with the rest of the system.

I tried to do it anyways with Timer4, and it gives me a flashing red light that I think translates hard fault

The code I’m trying to use is copied almost directly from the nrf52 timer example from Nordic.

const nrf_drv_timer_t beeptimer = NRF_DRV_TIMER_INSTANCE(4);

void testtimer(nrf_timer_event_t event_type, void *p_context) {
    Serial.println("hi");
}


//TODO: FREQUENCY INPUT LIMITS
void testTimer()
{
   
    //set up timer
    ticks = 1000;
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    int err_code = nrf_drv_timer_init(&beeptimer, &timer_cfg, testtimer);
    Log.error("Timer error %d", err_code);

    nrf_drv_timer_extended_compare(&beeptimer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    nrf_drv_timer_enable(&beeptimer);
    
    
}

Any suggestions would be appreciated,

Thanks!

Timer 4 is normally used by NFC, so that is a good choice unless you need NFC.

  • 0: Softdevice - do not use
  • 1: Radio - Used by BLE (and mesh)
  • 2: Usart (Serial1) Can use if not using Serial1.
  • 3: Usart (Serial2 on Xenon) Cannot be used on Argon or Boron because it’s required by NCP.
  • 4: NFC - recommended (unless you need NFC).

Also I would not call Serial.print from a hardware timer callback. It’s not interrupt safe and will eventually cause a SOS hard fault.

1 Like

So, I’m still getting a hard fault when I try to do this. Suggestions?

#include "nrf_timer.h"
#include "nrf_drv_timer.h"

const nrf_drv_timer_t beeptimer = NRF_DRV_TIMER_INSTANCE(4);

SYSTEM_MODE(MANUAL)

volatile bool pinswitch = 0;
void timerPinToggle(nrf_timer_event_t event_type, void *p_context)
{   
    if(pinswitch) {
        digitalWriteFast(A5, HIGH);
    } else {
        digitalWriteFast(A5, LOW);
    }
}

void testtimer()
{
    //calculate how often to fire the timer
    int ticks = 16000000 / 512;

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    int err_code = nrf_drv_timer_init(&beeptimer, &timer_cfg, timerPinToggle);
    nrf_drv_timer_extended_compare(&beeptimer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    nrf_drv_timer_enable(&beeptimer);
    
}

void setup() {
  testtimer();
}

void loop() {
}

Hi @AndrewM did you get timer to work? I also am trying to use Timer4 on my Boron

The problem is most likely that you need to use attachInterruptDirect() to get the interrupt to go into user code instead of into the system when using the nRF52 SDK from user firmware. There’s an example of doing this in the ADCDMAGen3_RK library, which is uses the ADC DMA hardware, but also needs a timer, so just copy the timer code out of it.

You use attachInterruptDirect(TIMER4_IRQn, nrfx_timer_4_irq_handler, false) regardless of what your interrupt handler is. What this does is connect the copy of the nRF52 SDK in user firmware to the hardware interrupt. You still pass your own callback to nrfx_timer_init() but without doing the attachInterruptDirect() step the interrupt goes to the interrupt handler in the system copy of the nRF52 SDK.

1 Like