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 Children
  • I will advice against using stalling for creating delays, regardless of the SDK version used. By default, the system clock in Zephyr runs from the 32.768 kHz clcok, which will not allow you to achieve the frequency you want. Using interrupts will allow you to set the priority of the task higher than other tasks in the application, and it will allow you to put the CPU to sleep for longer periods of time.

Related