Timers and Callbacks
Timers and interrupts are essential concepts in embedded systems programming. In this tutorial, we will take a look at how to use timers and interrupts in RIOT.
There are two different approaches to timers, you can either use interrupts or polling.
Both have their advantages and disadvantages, but in general, using interrupts is more efficient and allows you to do other things while waiting for the timer to expire instead of constantly checking if the timer has expired.
Step 1: Using Timers
In the hello world program we created in the previous tutorial,
we used the ztimer
module to sleep for 3 seconds before printing “Hello World!” to the console.
But what if we want to do something else while waiting for the timer to expire? Let’s take a closer look at how we can use timers in RIOT.
Step 1.1: Creating a Callback
Timers are a way to schedule tasks to be executed at a later time. In RIOT, you have to tell the timers two things: the time when the timer should expire and the function that should be called when the timer expires.
Lets start by creating the callback that the timer will call when it expires.
Go into your main.c
file and add the following code:
void timer_callback(void *arg) { /* Cast the received pointer "arg" to a C String type */ char *message = (char *)arg;
/* Print the message */ puts(message);}
This function takes a single argument, a pointer to a string,
and prints the string to the console. Congrats, you have created a callback function,
now all that is left is to create the timer and schedule it.
To do that lets restructure our main
function to use the timer.
Step 1.2: Scheduling the Timer
Go into your main
function and include the following code:
int main(void) { /* Create a timer */ ztimer_t timer = {.callback = timer_callback, .arg = "3 seconds have passed!"};
This code creates a timer and initializes it with the callback function we
created earlier and a message that will be printed when the timer expires.
Now all that is left is to actually start the timer. To do that,
we need to simply call the ztimer_set
function with the timer we created as an argument.
/* Set the timer to fire in 3 seconds */ ztimer_set(ZTIMER_SEC, &timer, 3);
This code tells the timer to fire in 3 seconds. The first argument specifies which type of clock we want to use, the second argument is the timer we created, and the third argument is the time in seconds.
Step 1.3: Running the Program
Now that we have created the timer and scheduled it, we can run the program.
Compile the program using make
and flash it to your board using make flash
.
If you look into the terminal via make term
you should see the message
“3 seconds have passed!” printed to the console after 3 seconds.
That’s all there is to it! You have successfully used a timer in RIOT. Now you can do other things while waiting for the timer to expire, instead of constantly checking if the timer has expired. For example, lets use our knowledge from before to let the main thread go to sleep for 5 seconds and then print a message.
/* Sleep for 5 seconds */ ztimer_sleep(ZTIMER_SEC, 5);
puts("5 seconds have passed!");
return 0;
Conclusion
In this tutorial, we learned how to use timers in RIOT. We created a callback function that prints a message to the console and scheduled a timer to call the callback function after 3 seconds.