Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Timer can't generate a <10 μs clock, what did I do wrong?

Hi Nordic community,

I'm trying to generate a 1 MHz base clock with one of the peripheral timer, and in the timer ISR does some GPIO toggling. 

I followed the nRF5 SDK example and just toggle one GPIO in the ISR to test the clock frequency. I notice, for some reason, the fastest clock I can get here is ~100 kHz (10.6 μs period).

Would you help me check what I did wrong?

Here is the relevant code snippet in main function:

    nrf_gpio_cfg_output(BSP_LED_1);
    nrf_gpio_pin_set(BSP_LED_1);
    timer_init(&TIMER1, 1);
    timer_enable(&TIMER1);
    while(1)
    {
        __WFI();
    }

Here is the timer_init definition:

void timer_init(nrfx_timer_t const * const p_instance, uint32_t time_us)
{
    uint32_t time_ticks;
    nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG;               // Start with default settings for the timer instance
    timer_config.bit_width = NRF_TIMER_BIT_WIDTH_16;
    timer_config.frequency = NRF_TIMER_FREQ_1MHz;

    APP_ERROR_CHECK(nrfx_timer_init(p_instance, &timer_config, timer_irq_handler)); // Initialize the timer
    time_ticks = nrfx_timer_us_to_ticks(p_instance, time_us);                   // Calculate time tick needed for the initialized timer based on its clock config
    
    switch(p_instance->instance_id)
    {
      // case NRFX_CONCAT_3(NRFX_TIMER, 0, _INST_IDX):
      //   nrfx_timer_extended_compare(p_instance, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);                                 // Setting the timer channe0 in the extended compare mode
      //   break;      
      case NRFX_CONCAT_3(NRFX_TIMER, 1, _INST_IDX):
        nrfx_timer_extended_compare(p_instance, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);                                 // Setting the timer channel in the extended compare mode
        break;
      // case NRFX_CONCAT_3(NRFX_TIMER, 2, _INST_IDX):
      //   nrfx_timer_extended_compare(p_instance, NRF_TIMER_CC_CHANNEL2, time_ticks, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);                                 // Setting the timer channel in the extended compare mode
      //   break;
      // case NRFX_CONCAT_3(NRFX_TIMER, 3, _INST_IDX):
      //   nrfx_timer_extended_compare(p_instance, NRF_TIMER_CC_CHANNEL3, time_ticks, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, true);                                 // Setting the timer channel in the extended compare mode
      //   break;
      default:
        break;
    }
}

And here is the timer irq handler

static void timer_irq_handler(nrf_timer_event_t event_type, void *p_context)    // Timer handler is only used in timer mode not counter mode
{
  switch(event_type)
  {
    // case NRF_TIMER_EVENT_COMPARE0:
    //   nrf_gpio_pin_toggle(BSP_LED_1);
    //   break;
    case NRF_TIMER_EVENT_COMPARE1:                                              // The event type is based on the timer setting
      nrf_gpio_pin_toggle(BSP_LED_1);
      //NRF_LOG_INFO("TIMER");
      break;
    // case NRF_TIMER_EVENT_COMPARE2:
    //   nrf_gpio_pin_set(BSP_LED_0);
    //   break;
    // case NRF_TIMER_EVENT_COMPARE3:
    //   break;
    default:
      break;
  }
}

Lastly, the timer_enable function just calls 

nrfx_timer_enable
 .

Really appreciate your help.

Thanks.

Richard

Parents Reply
  • You may try polling the register directly instead of using interrupt, but it is not a good long-term solution if you want to keep low power and allow the CPU to perform other tasks. 

    You should also try the timer code in a standalone application without the Softdevice present, to see if you get the expected latency.

    If you want fully predictable latency, you need to use PPI to trigger tasks when the timer fires, but if this is a viable solution in your application depends on what you want the timer to do.

Children
Related