1.. _timers_v2: 2 3Timers 4###### 5 6A :dfn:`timer` is a kernel object that measures the passage of time 7using the kernel's system clock. When a timer's specified time limit 8is reached it can perform an application-defined action, 9or it can simply record the expiration and wait for the application 10to read its status. 11 12.. contents:: 13 :local: 14 :depth: 2 15 16Concepts 17******** 18 19Any number of timers can be defined (limited only by available RAM). Each timer 20is referenced by its memory address. 21 22A timer has the following key properties: 23 24* A **duration** specifying the time interval before the timer 25 expires for the first time. This is a :c:type:`k_timeout_t` value that 26 may be initialized via different units. 27 28* A **period** specifying the time interval between all timer 29 expirations after the first one, also a :c:type:`k_timeout_t`. It must be 30 non-negative. A period of ``K_NO_WAIT`` (i.e. zero) or 31 ``K_FOREVER`` means that the timer is a one-shot timer that stops 32 after a single expiration. (For example then, if a timer is started 33 with a duration of 200 and a period of 75, it will first expire 34 after 200 ms and then every 75 ms after that.) 35 36* An **expiry function** that is executed each time the timer expires. 37 The function is executed by the system clock interrupt handler. 38 If no expiry function is required a ``NULL`` function can be specified. 39 40* A **stop function** that is executed if the timer is stopped prematurely 41 while running. The function is executed by the thread that stops the timer. 42 If no stop function is required a ``NULL`` function can be specified. 43 44* A **status** value that indicates how many times the timer has expired 45 since the status value was last read. 46 47A timer must be initialized before it can be used. This specifies its 48expiry function and stop function values, sets the timer's status to zero, 49and puts the timer into the **stopped** state. 50 51A timer is **started** by specifying a duration and a period. 52The timer's status is reset to zero, and then the timer enters 53the **running** state and begins counting down towards expiry. 54 55Note that the timer's duration and period parameters specify 56**minimum** delays that will elapse. Because of internal system timer 57precision (and potentially runtime interactions like interrupt delay) 58it is possible that more time may have passed as measured by reads 59from the relevant system time APIs. But at least this much time is 60guaranteed to have elapsed. 61 62When a running timer expires its status is incremented 63and the timer executes its expiry function, if one exists; 64If a thread is waiting on the timer, it is unblocked. 65If the timer's period is zero the timer enters the stopped state; 66otherwise, the timer restarts with a new duration equal to its period. 67 68A running timer can be stopped in mid-countdown, if desired. 69The timer's status is left unchanged, then the timer enters the stopped state 70and executes its stop function, if one exists. 71If a thread is waiting on the timer, it is unblocked. 72Attempting to stop a non-running timer is permitted, 73but has no effect on the timer since it is already stopped. 74 75A running timer can be restarted in mid-countdown, if desired. 76The timer's status is reset to zero, then the timer begins counting down 77using the new duration and period values specified by the caller. 78If a thread is waiting on the timer, it continues waiting. 79 80A timer's status can be read directly at any time to determine how many times 81the timer has expired since its status was last read. 82Reading a timer's status resets its value to zero. 83The amount of time remaining before the timer expires can also be read; 84a value of zero indicates that the timer is stopped. 85 86A thread may read a timer's status indirectly by **synchronizing** 87with the timer. This blocks the thread until the timer's status is non-zero 88(indicating that it has expired at least once) or the timer is stopped; 89if the timer status is already non-zero or the timer is already stopped 90the thread continues without waiting. The synchronization operation 91returns the timer's status and resets it to zero. 92 93.. note:: 94 Only a single user should examine the status of any given timer, 95 since reading the status (directly or indirectly) changes its value. 96 Similarly, only a single thread at a time should synchronize 97 with a given timer. ISRs are not permitted to synchronize with timers, 98 since ISRs are not allowed to block. 99 100Implementation 101************** 102 103Defining a Timer 104================ 105 106A timer is defined using a variable of type :c:struct:`k_timer`. 107It must then be initialized by calling :c:func:`k_timer_init`. 108 109The following code defines and initializes a timer. 110 111.. code-block:: c 112 113 struct k_timer my_timer; 114 extern void my_expiry_function(struct k_timer *timer_id); 115 116 k_timer_init(&my_timer, my_expiry_function, NULL); 117 118Alternatively, a timer can be defined and initialized at compile time 119by calling :c:macro:`K_TIMER_DEFINE`. 120 121The following code has the same effect as the code segment above. 122 123.. code-block:: c 124 125 K_TIMER_DEFINE(my_timer, my_expiry_function, NULL); 126 127Using a Timer Expiry Function 128============================= 129 130The following code uses a timer to perform a non-trivial action on a periodic 131basis. Since the required work cannot be done at the interrupt level, 132the timer's expiry function submits a work item to the 133:ref:`system workqueue <workqueues_v2>`, whose thread performs the work. 134 135.. code-block:: c 136 137 void my_work_handler(struct k_work *work) 138 { 139 /* do the processing that needs to be done periodically */ 140 ... 141 } 142 143 K_WORK_DEFINE(my_work, my_work_handler); 144 145 void my_timer_handler(struct k_timer *dummy) 146 { 147 k_work_submit(&my_work); 148 } 149 150 K_TIMER_DEFINE(my_timer, my_timer_handler, NULL); 151 152 ... 153 154 /* start a periodic timer that expires once every second */ 155 k_timer_start(&my_timer, K_SECONDS(1), K_SECONDS(1)); 156 157Reading Timer Status 158==================== 159 160The following code reads a timer's status directly to determine 161if the timer has expired or not. 162 163.. code-block:: c 164 165 K_TIMER_DEFINE(my_status_timer, NULL, NULL); 166 167 ... 168 169 /* start a one-shot timer that expires after 200 ms */ 170 k_timer_start(&my_status_timer, K_MSEC(200), K_NO_WAIT); 171 172 /* do work */ 173 ... 174 175 /* check timer status */ 176 if (k_timer_status_get(&my_status_timer) > 0) { 177 /* timer has expired */ 178 } else if (k_timer_remaining_get(&my_status_timer) == 0) { 179 /* timer was stopped (by someone else) before expiring */ 180 } else { 181 /* timer is still running */ 182 } 183 184Using Timer Status Synchronization 185================================== 186 187The following code performs timer status synchronization to allow a thread 188to do useful work while ensuring that a pair of protocol operations 189are separated by the specified time interval. 190 191.. code-block:: c 192 193 K_TIMER_DEFINE(my_sync_timer, NULL, NULL); 194 195 ... 196 197 /* do first protocol operation */ 198 ... 199 200 /* start a one-shot timer that expires after 500 ms */ 201 k_timer_start(&my_sync_timer, K_MSEC(500), K_NO_WAIT); 202 203 /* do other work */ 204 ... 205 206 /* ensure timer has expired (waiting for expiry, if necessary) */ 207 k_timer_status_sync(&my_sync_timer); 208 209 /* do second protocol operation */ 210 ... 211 212.. note:: 213 If the thread had no other work to do it could simply sleep 214 between the two protocol operations, without using a timer. 215 216Suggested Uses 217************** 218 219Use a timer to initiate an asynchronous operation after a specified 220amount of time. 221 222Use a timer to determine whether or not a specified amount of time has 223elapsed. In particular, timers should be used when higher precision 224and/or unit control is required than that afforded by the simpler 225:c:func:`k_sleep` and :c:func:`k_usleep` calls. 226 227Use a timer to perform other work while carrying out operations 228involving time limits. 229 230.. note:: 231 If a thread needs to measure the time required to perform an operation 232 it can read the :ref:`system clock or the hardware clock <kernel_timing>` 233 directly, rather than using a timer. 234 235Configuration Options 236********************* 237 238Related configuration options: 239 240* None 241 242API Reference 243************* 244 245.. doxygengroup:: timer_apis 246