Introduction

A timer provides a way to perform a delayed action or a periodic action with user specified time. The timer waits until a certain time interval has elapsed and then fires executing user defnied function called handler. The use of timers are handled by functions in sm_timers.h library.

Getting started

To get started with timers you will need :

Take Smablo development board from your Smablo Development kit and place CPU on the described connector like in the pictures and video below:

{.force-inline} {.force-inline}

When you’ve done connecting Shield you can connect Smablo Development board to your computer with USB cable.

Minimal code

Minimal code will briefly show you how to use timers. This example uses timer to update counter variable every 1 second.

//1
#include "nrf_log.h"
#include "sm_timer.h"
#include "app_error.h"

//2
//timer definition
SM_TIMER_DEF(my_timer);

//helper variable 
static uint16_t counter = 0;

//5
//user defibned handler
static void timer_handler(void * p_context)
{
    counter++;

    //show counter value on screen 
    NRF_LOG_RAW_INFO("Counter value = %d \n\r", counter);

}

void timer_demo(void)
{   
//3
    //create my_timer timer to repeatedly call timer_handler handler function
    ret_code_t err_code = sm_timer_create(&my_timer, SM_TIMER_MODE_REPEATED, timer_handler );
    APP_ERROR_CHECK(err_code);
//4
    //Start timer with 1000ms interval 
    err_code = sm_timer_start(my_timer, SM_TIMER_TICKS(1000), NULL);
    APP_ERROR_CHECK(err_code);

}

In point 1 we including all the libraries we will use in this project:

  • #include "nrf_log.h" contains macros that we will use to print values on screen for more info see log marcos
  • #include "sm_timer.h" contains all the functions needed to use the timers
  • #include "app_error.h" is libary that will help us to check for errors

In point 2 to use timer we need to create its definition first. We can do that with SM_TIMER_DEF macro, in our case SM_TIMER_DEF(my_timer); results in new my_timer definition.

In point 3 we create the the my_timer from its definition createrd in previous point. To create the timer we use sm_timer_create function that takes 3 parameters:

  • addres of timer definition
  • timer operation mode from sm_timer_mode_t enum :
    ///timer mode
    typedef enum
    {
      SM_TIMER_MODE_SINGLE_SHOT,    ///< The timer will expire only once
      SM_TIMER_MODE_REPEATED        ///< The timer will restart each time it expires
    } sm_timer_mode_t;

    We can choose between SM_TIMER_MODE_SINGLE_SHOT that will fire the timer handler only once and SM_TIMER_MODE_REPEATED that will fire timer handler repeatedly with time defined in sm_timer_start function.

  • pointer to handler function that is user defined function that will be called after timer timeout in this case called timer_handler

In point 4 we are starting our timer with sm_timer_start function, from this moment our timer will start counting. To start the timer function needs 3 parameters:

  • timer to start which in our case is called my_timer
  • time to wait between calls which we set with SM_TIMER_TICKS marco. This macro sets the time in ms so to have the call every 1 second we need to set the macro to SM_TIMER_TICKS(1000).
  • pointer to the context that we want to send to the handler. In this case we don't need it so we can set this parameter as NULL

In point 5 we have our timer handler function which will execute every 1 s, update the counter variable and print its value on screen using log marcos

sm_timers library reference

sm_timer_init

Prototype:

ret_code_t sm_timer_init(void);

Function is used to initialize the timers. You don't need to use this function because it is already called upon system initialization. Function returns ret_code_t value which indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating cause or reason for failure is provided.

sm_timer_create

Prototype:

ret_code_t sm_timer_create(sm_timer_id_t const * p_timer_id, sm_timer_mode_t mode, sm_timer_timeout_handler_t timeout_handler);

Function is used for creating the timer from definition. Function returns ret_code_t value which indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating cause or reason for failure is provided. For this function the return error codes are following:

  • NRF_SUCCESS if the timer was successfully created.
  • NRF_ERROR_INVALID_PARAM if a parameter was invalid.
  • NRF_ERROR_INVALID_STATE if the application timer module has not been initialized or the timer is running.

Function takes 3 paramters:

  • p_timer_id type sm_timer_id_t which is pointer to the ID of the timer which we want to create. The timer definition should be created with use of SM_TIMER_DEF macro.
  • mode type sm_timer_mode_t

    ///timer mode
    typedef enum
    {
      SM_TIMER_MODE_SINGLE_SHOT,    ///< The timer will expire only once
      SM_TIMER_MODE_REPEATED        ///< The timer will restart each time it expires
    } sm_timer_mode_t;

    which timer operation mode. We can choose between SM_TIMER_MODE_SINGLE_SHOT that will fire the timer handler only once and SM_TIMER_MODE_REPEATED that will fire timer handler repeatedly with time defined in sm_timer_start function.

  • timeout_handler type sm_timer_timeout_handler_t pointer to handler function that is user defined function that will be called after timer timeout. The use of this function was shown in Minimal code chapter

sm_timer_start

Prototype:

ret_code_t sm_timer_start(sm_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context);

Function is used for starting the timer. After executing this function the timer start counting to execite timer handler defined in sm_timer_create function. Function returns ret_code_t value which indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating cause or reason for failure is provided. For this function the return error codes are following:

  • NRF_SUCCESS if the timer was successfully started.
  • NRF_ERROR_INVALID_PARAM if a parameter was invalid.
  • NRF_ERROR_INVALID_STATE if the application timer module has not been initialized or the timer has not been created.
  • NRF_ERROR_NO_MEM if the timer operations queue was full.

    Function takes 3 parameters:

  • timer_id type sm_timer_id_t the ID of the timer we want to start. The timer definition should be created with use of SM_TIMER_DEF macro.
  • timeout_ticks type uint32_t which is timer timeout ticks and specifies how many ticks from now it shall time out and execute the timer handler. For your convenience SM_TIMER_TICKS macro was created that will convert the time in ms you want to the timer ticks. For example if we wanted 1 second time we will type SM_TIMER_TICKS(1000);
  • * p_context type void is the general purpose pointer that is passed to the timeout handler. Can be NULL if we don't want to use it.

The use of this function was shown in Minimal code chapter.

sm_timer_stop

Prototype:

ret_code_t sm_timer_stop(sm_timer_id_t timer_id);

Function is used for stopping the specified timer.Function returns ret_code_t value which indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating cause or reason for failure is provided. For this function the return error codes are following:

  • NRF_SUCCESS if the timer was successfully stopped.
  • NRF_ERROR_INVALID_PARAM if a parameter was invalid.
  • NRF_ERROR_INVALID_STATE if the application timer module has not been initialized or the timer has not been created.
  • NRF_ERROR_NO_MEM if the timer operations queue was full.

Function takes one parameter timer_id type sm_timer_id_t which is the timer ID we want to stop.

The example below shows how to use sm_timer_stop function. Example will execute timer_handler five times with my_timer and after the sm_timer_stop will be called and the timer will be stopped.

#include "nrf_log.h"
#include "sm_timer.h"
#include "app_error.h"

//timer definition
SM_TIMER_DEF(my_timer);

//helper value
static uint16_t counter = 0;

//user defned handler
static void timer_handler(void * p_context)
{

    if (counter >= 5 ) 
    {
        ret_code_t err_code = sm_timer_stop(my_timer );

        APP_ERROR_CHECK(err_code);

        return;
    }

    counter++;

    NRF_LOG_RAW_INFO("Counter value = %d \n\r", counter);

}
void timer_demo(void)
{   
    //create my_timer timer to repeatedly call timer_handler handler function
    ret_code_t err_code = sm_timer_create(&my_timer, SM_TIMER_MODE_REPEATED, timer_handler );
    APP_ERROR_CHECK(err_code);

    //Start timer with 1000ms interval 
    err_code = sm_timer_start(my_timer, SM_TIMER_TICKS(1000), NULL);
    APP_ERROR_CHECK(err_code);

} 

sm_timer_stop_all

Prototype:

ret_code_t sm_timer_stop_all(void);

Function is used for stopping all the timers. Function returns ret_code_t value which indicates success or failure of an API procedure. In case of failure, a comprehensive error code indicating cause or reason for failure is provided. For this function the return error codes are following:

  • NRF_SUCCESS if the timer was successfully stopped.
  • NRF_ERROR_INVALID_STATE if the application timer module has not been initialized or the timer has not been created.
  • NRF_ERROR_NO_MEM if the timer operations queue was full.

Function use is similar to sm_timer_stop function. The difference is that sm_timer_stop_all will stop all timers.