NRF54L15 Timer running much slower than expected

Running on Fanstel BM15M module (nrf54L15) SDK v3.1.1, I seeing a huge timing error when trying to implement a simple timer function.  In the code below, I believe I have followed the examples to implement a timer (24) with a 1MHz frequency and a 100 count interval which should yield a 10kHz interrupt. But using the callback function to toggle a debug pin and monitoring that pin with an O'scope, I see a stable 128us interval instead of 100us - a 28% error.  I am running off the internal oscillator. The internal crystal is 250ppm which should yield at most an error 2.5us

Please tell me what I am doing wrong.  Side note when I try to use the external 32MHz crystal per the notes provided by Fanstel, I get stuck with an assertion error - "err = mpsl_init(&clock_cfg, CONFIG_MPSL_LOW_PRIO_IRQN, m_assert_handl" - but that is perhaps a discussion for another day.

prf.conf lines:

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_250PPM=y

Timer setup in main.c:

/****************** Main Loop timer setup  ********************/
nrfx_timer_t main_loop_tmr_inst = NRFX_TIMER_INSTANCE(24); // enabled in prf....conf

/* Define the IR LED timeslot interval */
#define MAIN_LOOP_TMR_INTERVAL_US 100

uint16_t tenth_sec_count = 0;
uint16_t tenth_ms_count = 0;

/* Implement timer callback handler function */
 void main_tmr_cb(struct k_timer *timer)
{  
    tenth_ms_count++;
    setGPIO(DEBUG_OUT,tenth_ms_count % 2);
    if(tenth_ms_count > 999){
        tenth_ms_count = 0;
        tenth_sec_count++;
    }
}

/*  Define the IR timeslot timer instance */
K_TIMER_DEFINE(main_loop_tmr, main_tmr_cb, NULL);

void configure_main_loop_tmr(void)
{
    nrfx_err_t err;
#if defined(__ZEPHYR__)
    IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(24)), IRQ_PRIO_LOWEST,
                nrfx_timer_22_irq_handler, &main_loop_tmr_inst, 0);
#endif

    /*  Declaring timer config and intialize nrfx_timer instance. */
    nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(1000000); // 1MHz
    err = nrfx_timer_init(&main_loop_tmr_inst, &timer_config, NULL);
    if (err != NRFX_SUCCESS) {
        printk("nrfx_timer_init error: %08x", err);
        return;
    }

    /* Set compare channel 0 to generate event every MAIN_LOOP_TMR_INTERVAL_US. */
    uint16_t timer_ticks = nrfx_timer_us_to_ticks(&main_loop_tmr_inst, MAIN_LOOP_TMR_INTERVAL_US); //  10kHz

    nrfx_timer_extended_compare(&main_loop_tmr_inst, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
    nrfx_timer_enable(&main_loop_tmr_inst);  // enabled with "true" flag in nrfx_timer_extended_compare
    k_timer_start(&main_loop_tmr, K_NO_WAIT, K_USEC(MAIN_LOOP_TMR_INTERVAL_US));
}

Parents
  • Thank you.  That addresses my issue.  

    A couple follow up questions. 

    I see that the output on my debug pin varies some from cycle to cycle, I assume this is related to other interrupts having priority.  I don't expect I can get around BLE interrupts, but I would like this timer to be as regular as possible.  I see in the IRQ_CONNECT marco the IRQ_PRIO_LOWEST VALUE -does this select the lowest possible the lowest priority IRQ, or does it assign the lowest available IRQ number which is the highest priority?  Do lower numbered timers has lower number IRQs by default.  Asked another way, in a system with several timers, how do I control which one has the highest priority IRQ?

    Also, I would like to resync this timer with an periodic external event (a GPIO interrupt) is nrfx_timer_clear() the correct call or is there a better way to resync the timer?  Do I need to disable the timer to clear it, or will that just cause an unwanted delay in the syncing process.

Reply
  • Thank you.  That addresses my issue.  

    A couple follow up questions. 

    I see that the output on my debug pin varies some from cycle to cycle, I assume this is related to other interrupts having priority.  I don't expect I can get around BLE interrupts, but I would like this timer to be as regular as possible.  I see in the IRQ_CONNECT marco the IRQ_PRIO_LOWEST VALUE -does this select the lowest possible the lowest priority IRQ, or does it assign the lowest available IRQ number which is the highest priority?  Do lower numbered timers has lower number IRQs by default.  Asked another way, in a system with several timers, how do I control which one has the highest priority IRQ?

    Also, I would like to resync this timer with an periodic external event (a GPIO interrupt) is nrfx_timer_clear() the correct call or is there a better way to resync the timer?  Do I need to disable the timer to clear it, or will that just cause an unwanted delay in the syncing process.

Children
Related