---
title: "Timers"
canonical_url: https://developer.repebble.com/pebbleos/docs/samples/kernel/timer/
last_updated: 2026-11-13
sdk_version: 4.44
---
# Timers

Source: https://developer.repebble.com/pebbleos/docs/samples/kernel/timer/

This sample starts a timer that repeats five times by starting itself again from its callback, which wakes `main()` with a semaphore when done. It then starts one, reads how long it has left, and stops it.

The callback runs in the tick interrupt, so it only counts and signals. Work that has to block belongs in [delayed work](https://developer.repebble.com/pebbleos/docs/samples/kernel/delayed_work.md), which runs on a thread.

Run:

`pbl samples samples/kernel/timer`

Boards:

every board

## Sources

src/main.c

```
#include \<inttypes.h\>#include \<pbl/kernel/delay.h\>#include \<pbl/kernel/sem.h\>#include \<pbl/kernel/time.h\>#include \<pbl/kernel/timer.h\>#include \<pbl/logging/logging.h\>#include \<pbl/util/misc.h\>#define BLINKS 5#define BLINK\_PERIOD\_MS 20/\* A timer lives in the object it acts on, which its callback gets back. \*/struct blinker {struct pbl\_timer timer;struct pbl\_sem done;unsigned int blinks;uint64\_t last\_ms;};/\* Callbacks run in the tick interrupt: keep them short, and never block. \*/static void prv\_blink(struct pbl\_timer \*timer) {struct blinker \*blinker = container\_of(timer, struct blinker, timer);blinker-\>blinks++;blinker-\>last\_ms = pbl\_uptime\_ms();/\* Timers are one-shot: one that repeats starts itself again. \*/if (blinker-\>blinks \< BLINKS) {pbl\_timer\_start(timer, PBL\_MSEC(BLINK\_PERIOD\_MS));} else {pbl\_sem\_give(&blinker-\>done);}}static struct blinker s\_blinker = {.timer = PBL\_TIMER\_INITIALIZER(prv\_blink),.done = PBL\_SEM\_INITIALIZER(0, 1),};int main(void) {uint64\_t start\_ms = pbl\_uptime\_ms();int ret;pbl\_timer\_start(&s\_blinker.timer, PBL\_MSEC(BLINK\_PERIOD\_MS));ret = pbl\_sem\_take(&s\_blinker.done, PBL\_SEC(1));if (ret != 0) {PBL\_LOG\_ERR("main: timer did not expire (%d)", ret);return ret;}PBL\_LOG\_INFO("main: %u blinks, the last one %s %u ms after the start", s\_blinker.blinks,s\_blinker.last\_ms - start\_ms \>= BLINKS \* BLINK\_PERIOD\_MS ? "at least" : "less than",BLINKS \* BLINK\_PERIOD\_MS);s\_blinker.blinks = 0;pbl\_timer\_start(&s\_blinker.timer, PBL\_SEC(10));pbl\_sleep\_ms(10);PBL\_LOG\_INFO("main: started for 10 s, active: %s, more than 5 s left: %s",pbl\_timer\_is\_active(&s\_blinker.timer) ? "yes" : "no",pbl\_ticks\_to\_ms(pbl\_timer\_remaining(&s\_blinker.timer)) \> 5000 ? "yes" : "no");pbl\_timer\_stop(&s\_blinker.timer);PBL\_LOG\_INFO("main: stopped, active: %s", pbl\_timer\_is\_active(&s\_blinker.timer) ? "yes" : "no");pbl\_sleep\_ms(20);PBL\_LOG\_INFO("main: stopped before it expired, %u blinks since", s\_blinker.blinks);PBL\_LOG\_INFO("Sample done");return 0;}
```

## Output

```
main: 5 blinks, the last one at least 100 ms after the start
main: started for 10 s, active: yes, more than 5 s left: yes
main: stopped, active: no
main: stopped before it expired, 0 blinks since
Sample done
```

Generated from PebbleOS [f4926c952](https://github.com/coredevices/pebbleos/commit/f4926c952bf9b82bce9e3cdb44645a59531c0ee9). This page is maintained in the pebbleos repository: [docs/samples/kernel/timer.md](https://github.com/coredevices/pebbleos/blob/f4926c952bf9b82bce9e3cdb44645a59531c0ee9/docs/samples/kernel/timer.md).
