This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Adding a timer to a BLE application

I am working on adding a periodic timer to an existing and running application to add some new features.

I mimic exactly what is done in the peripheral/timer_pca10028 example, except the following minor(?) changes:

  • Variable/function names and add some #define
  • Change #define TIMER0_ENABLED value from 0 to 1
  • Change handler to print out an incrementing static uint8 instead of toggling LEDs

The app stopped working after those change, and was printing out UART rubbishes instead of what it had done before that. Since I remember reading somewhere here that TIMER0 canot be used, I made some more changes:

  • Change timer instance from NRF_DRV_TIMER_INSTANCE(0) to NRF_DRV_TIMER_INSTANCE(1)
  • Change #define TIMER0_ENABLED back to 0
  • Change #define TIMER1_ENABLED value from 0 to 1

Now the timer works. However, the timer handler is called way too quickly. There must be tens of printf fired off every seconds. I could not figure out why.

Here is my timer related code for referrence

#define INTERVAL    1000            /**< Number of mili seconds between interrupts */
const nrf_drv_timer_t TIMER = NRF_DRV_TIMER_INSTANCE(1);

static void ble_stack_init(void)
{
  uint32_t err_code;

  // Initialize the SoftDevice handler module.
  SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, NULL);
  // Other non-timer codes...
}

void timer_event_handler(nrf_timer_event_t event_type, void* p_context)
{   
  static uint8_t i;
  i++;
  printf("%x\n", i);
}

// main()
uint32_t time_ms = INTERVAL; // I tried using 500 or 5000 here, but they also don't work
uint32_t time_ticks;
uint32_t err_code;
err_code = nrf_drv_timer_init(
  &TIMER,
  NULL,
  timer_event_handler);
if (err_code == NRF_SUCCESS) {
  printf("NRF_SUCCESS\n");
} else {
  printf("%08x\n", err_code);
}
APP_ERROR_CHECK(err_code);
time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER, time_ms);
nrf_drv_timer_extended_compare(&STIMER, 
  NRF_TIMER_CC_CHANNEL0, 
  time_ticks, 
  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, 
  true); 
nrf_drv_timer_enable(&TIMER);

So my question is:

  1. Was the reason the app failed to run with TIMER0 is that TIMER0 is used for some core functionality of a BLE app?

1.1. If yes, is it the APP_TIMER or something else?

1.2. If no, what would the cause TIMER0 not to work then?

1.3. Does this mean TIMER0 cannot be used anywhere else?

  1. Why is TIMER1 running so quickly? I suspect two places that could be the source of problem but do not understand them fully to work further on:

2.1. I understand that nrf_drv_timer_ms_to_ticks() would convert the ms time value passed to equivalent value in "ticks" for the timer parameter. Is this always dependable? The SDK documentation says that this function detects if overflow occurs, but I do not see any interruption in the application flow.

2.2. According to the this SDK documentation a "default configuration" is applied to the TIMER1 when nrf_drv_timer_init() was called with a second parameter of NULL. But what exactly is this "default configuration"?

Parents
  • Thanks to the tips from RK, I dived into the product specification and driver structure, and found the root of the problem.

    1. As RK said, TIMER0 cannot be used for anything because it is used by the SoftDevice
    2. Short answer is because TIMER1 is a 16-bit timer.

    2.1. While nrf_drv_timer_ms_to_ticks() does check for overflow, it only check if the ticks value is more than 32 bit. The function does not check if the ticks value is too big for the current timer. TIMER1 is only a 8/16 bit timer, so any ticks value greater than 0x0000ffff will have its MS 4 byte clipped off. My ticks value was 0xf42400, which means the actual value written on to the Capture/Compare register is 0x2400, about 1800 times shorter than intended.

    2.2. NRF_DRV_TIMER_DEFAULT_CONFIG(1) set TIMER1 to 16MHz, too fast to set an interrupt interval of 1s with a 16-bit Capture/Compare register. A custom nrf_drv_timer_config_t need to be passed for the second param of nrf_drv_timer_init() instead of NULL.

  • Hi Hieu,

    Were you able to resolved your problem?  it appears that I have the same problem

    when I tried to add TIMER1 to the project sample  "ble_app_uart" .

    Any advise is appreciated. Looking forward to your reply.

    Regards,

    JIMMY

  • This thread is complete with a proper answer.

    Your description is very little and not enough to conclude that your problem is related to this thread. I would strongly recommend you to create a new thread and try to get an answer. Please remember to be as descriptive as possible to get response from fellow enthusiastic devzone users 

Reply Children
No Data
Related