2016-04-08: Updated tutorial to cover SDK version 11.
The following topics will be included in this tutorial:
The tutorial will not cover all aspects of the application timer, but will focus on the most important uses and API functions.
It is expected that you have basic knowledge of how to use Keil in order to build and download your application to your kit. Refer to Getting Started in the SDK documentation if this is unfamiliar territory. It is also expected that you are familiar of the concept of interrupts and event handlers. Please refer to the Pin Change Interrupt Example if you need to refresh this topic.
Within the tutorial project folder there are subfolders for different boards:
To get started, download the example code. It configures GPIO inputs and outputs for the buttons and LED's that will be used in the tutorial. To build it, extract the compressed project to <SDK>\examples\peripheral. The example is intended for the zipped version of the SDK. It will not work with the Pack installer. If you need help with this please have a look at this thread on DevZone: Compiling github projects. Open the project file (.uvprojx) and hit Build. The application should compile without any errors or warnings.
Erase the flash of the DK using nRFgo Studio or nrfjprog in order to ensure that no SoftDevice is installed. You only have to do this once. The application can be downloaded to the DK from Keil by pressing Download. You should be able to control LED 1 with button 1 and 2, and control LED 2 using button 3 and 4.
The Application Timer library provides a user friendly way of using the Real Time Counter 1 (RTC1) peripheral to create multiple timer instances. The RTC uses the Low Frequency Clock (LFCLK). Most applications keep the LFCLK active at all times. When using a SoftDevice the LFCLK is always active. Therefor there is normally very little extra power consumption associated with using the application timer. As the clock is 32.768 kHz and the RTC is 24 bit, the time/tick resolution is limited, but it takes a substantial amount of time before the counter wrap around (from 0xFFFFFF to 0). The frequency of the RTC can be lowered by using the 12 bit (1/x) prescaler.
In this part of the tutorial you will configure the library, and use it to create timers that call your timeout event handlers. These can be called repeatedly at a configurable interval or once at a configurable time from now.
Refer to the Application Timer API Reference as needed.
Two C files have to be added to the project in order to use the application timer. Right click on the nRF_Drivers group in the project window. Click Add existing files to group 'nRF_Drivers' and add:
Then right click on the nRF_Libraries group in the project window. Click Add existing files to group 'nRF_Libraries' and add:
Now go to Project -> Options for target ... -> C/C++. From there, add the following directories to the Include Paths:
Then include the required header files by adding the following lines below the existing include statements:
As a SoftDevice is not enabled in this tutorial, the LFCLK must be requested explicitly. One way of doing this is using the Clock driver. Add the following function somewhere before main():
// Function starting the internal LFCLK oscillator.
// This is needed by RTC1 which is used by the application timer
// (When SoftDevice is enabled the LFCLK is always running and this is not needed).
static void lfclk_request(void)
uint32_t err_code = nrf_drv_clock_init();
Add a line calling lfclk_request() in the start of the main() function:
// Request LF clock.
The Application Timer should be initialized with the APP_TIMER_INIT() macro. This must be called before any other calls to the Application Timer API. The four parameters must be selected so that they meet the requirements of the application:
In this tutorial you will create 2 timers. Add the following defines (which represent the parameters described above) close to the top of your code:
// General application timer settings.
#define APP_TIMER_PRESCALER 15 // Value of the RTC1 PRESCALER register.
#define APP_TIMER_OP_QUEUE_SIZE 3 // Size of timer operation queues.
Then put this line in main() in order to initialize the app timer (after the call to lfclk_request()):
// Initialize the application timer module.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
An application timer in the repeated mode will restart each time it expires. Every time it expires the timeout handler will be called. This makes it suitable for performing a task at a regular interval, such as toggling a LED, which is what you will do now. In this section we will modify the application so that button 1 starts toggling of LED 1 using an application timer in repeated mode. Button 2 will stop the toggling by stopping the timer.
Application timers are created using app_timer_create(). This function takes three parameters:
First, create a variable that can hold the timer ID to be populated by app_timer_create(). Add the following line to your code, close to the top of the file:
Then you will have to create the timeout event handler. This will toggle LED 1 every time it is called. Add the following function to your code somewhere before the main() function:
// Timeout handler for the repeated timer
static void timer_a_handler(void * p_context)
I suggest you wrap the creation of the timer in a function, in order to keep a minimal main() function. Then the next timer you create in this tutorial can be created within the same function.
Add the following function to your code:
// Create timers
static void create_timers()
// Create timers
err_code = app_timer_create(&m_led_a_timer_id,
Add the following to main() before the main loop in order to call the function you just made:
// Create application timers.
Now the timer is created, but not started. In fact, we have not specified the time between timeouts yet. The timeout is specified in the number of ticks of the RTC1 including prescaling.
It is normally easier to relate to milliseconds than RTC ticks, and the APP_TIMER_TICKS macro is useful for converting a value in milliseconds to the corresponding number of ticks, depending on the prescaler settings.
You will now have to modify the button_handler() that is present in the example project in order to let button 1 start the timer. Remove the following code from button_handler():
..and replace it with this snippet:
err_code = app_timer_start(m_led_a_timer_id, APP_TIMER_TICKS(200, APP_TIMER_PRESCALER), NULL);
Declare the err_code variable before the switch statement by inserting the following line:
The app_timer_start function starts the specified timer (first parameter), and specifies how many ticks from now it shall time out (second parameter). The third parameter is a general purpose pointer that is passed to the timeout handler. It is set to NULL in this case as we do not use it. (It is represented by p_context in the timeout handler timer_a_handler() in this tutorial).
With this code in place, you should be able to build the application without any errors or warnings. Try to build and download it to the development kit (DK). Then you should be able to start toggling of LED 1 by pressing button 1. However, once the LED is toggling there is no way to stop it (other than resetting the chip).
In order to stop the LED from blinking you have to stop the timer. This is done using the app_timer_stop() function, which takes the timer ID as the only parameter. Modify the button_handler() so that app_timer_stop() is called when button 2 is pressed, by replacing the following code in the button_handler():
err_code = app_timer_stop(m_led_a_timer_id);
With the latest addition, build the code and download it to the target. You should now be able to stop the toggling of the LED by pressing button 2. The timer can be re-started any time by pressing button 1.
A application timer in single shot mode will expire only once. However, it can always be restarted. Moreover, the number of ticks before it times out can be set to a different value every time it is called (this is also the case for repeated timers).
In this part of the tutorial we will let button 3 start a single shot timer that lights LED 2 when it times out. The first time button 3 is pressed the timer will have a timeout of 1 second. Then the timeout will be incremented by 1 second every time the timer is started. We will keep the functionality of button 4 that it is used to turn off the LED.
Add a new timer ID below the existing m_led_a_timer_id by adding the following line:
Then create the timeout handler shall light LED 2 every time it is called. Add this snippet to your code:
// Timeout handler for the single shot timer
static void timer_b_handler(void * p_context)
Then modify the create_timers() by appending the following lines to the end of the function (note that the mode is APP_TIMER_MODE_SINGLE_SHOT):
err_code = app_timer_create(&m_led_b_timer_id,
Then update the button_handler() by removing:
...and replacing it with:
// Start single shot timer. Increase the timeout with 1 second every time.
timeout += 1000;
err_code = app_timer_start(m_led_b_timer_id, APP_TIMER_TICKS(timeout, APP_TIMER_PRESCALER), NULL);
Declare the static timeout variable before the switch statement by inserting the following line:
static uint32_t timeout = 0;
Build the code and download it to the target. If you press button 3 you will see that LED 2 is lit after 1 second. Then press button 4, and the LED turns dark. Now press button 3 again and observe that it takes 2 seconds before the LED is lit.
I'm new to this and I want to know how to run this tutorial in Segger embedded studio?
Hi Prasad, This is because nrf_nvic_state is declared in multiple files. While adding app-timer I added app_utilplatform. nrf_nvic_state is defined in mesh_softdevice_init.c as well as app_utilplatform.c. So I added this code snippet in app_utilplatform.c where nrf_nvic_state was already defined, and it worked.
/* Global nvic state instance, required by nrf_nvic.h */
extern nrf_nvic_state_t nrf_nvic_state;
Were you able to resolve this issue? I am facing this issue too...
I am trying to add app_timer in mesh 2.0.1. I am working with sdk 15. When adding app_util_platform, I am getting an error as multiple definition of nrf_nvic_state. Can somebody help me with this?
Hi, this tutorial is outdated for sdk13 as mentioned already in the comments, However the header still includes the function APP_TIMER_INIT() as comment and also app_timer_init() ? this is confusing. would be nice to have an updated tutorial. Thanks a lot.