1---
2title: Low Power Utility
3author: sclarson
4ms.author: sclarson
5description: This article is a summary of the Low Power utility APIs available in ThreadX.
6ms.date: 03/02/2021
7ms.topic: article
8ms.service: rtos
9---
10
11# ThreadX Low Power Utilities
12
13These low power utilities are intended to maintain ThreadX timers and the internal tick count while the processor is in a low-power/sleep state. The terms "low power" and "sleep" are used interchangeably throughout this document.
14
15The low power utilities may be used with any ThreadX port except SMP.
16
17## Installation of Low Power Utilities
18
19The ThreadX low power utilities are comprised of two files:
20
21 - [tx_low_power.c](tx_low_power.c)
22 - [tx_low_power.h](tx_low_power.h)
23
24These files can be built with the ThreadX library or built in the user application.
25
26## Detailed Description
27
28By default, ThreadX spins in an idle loop in the scheduler when there are no threads ready to run. It may be desireable to put the processor in a low power state while idle. Functions  ```tx_low_power_enter``` and ```tx_low_power_exit``` are designed to enter and exit low power mode, respectively.
29
30The ```tx_low_power_enter``` and ```tx_low_power_exit``` functions manage the ThreadX timers and invoke optional macros that the user must define in order to configure the hardware for low power mode. These macros are discussed in a section below.
31
32For convenience, the Cortex-M and RX ports have calls to the low power APIs already integrated into their schedulers. If symbol **TX_LOW_POWER** is defined, functions ```tx_low_power_enter``` and ```tx_low_power_exit``` are called in the scheduler idle loop. It is assumed that the processor will exit sleep mode and resume execution in the idle loop (or in an interrupt and then return to the idle loop). For processors that exhibit different behavior (such as waking from sleep at the reset vector), these low power functions may need to be called elsewhere.
33
34### Low Power Timer and Tick-less Low Power Mode
35
36If accurate timekeeping is not desired while in low power mode, macros **TX_LOW_POWER_TIMER_SETUP** and **TX_LOW_POWER_TICKLESS** do not need to be defined. The internal ThreadX tick count will not reflect the time spent in low power mode.
37
38If **TX_LOW_POWER_TIMER_SETUP** is defined, there are two use cases for timekeeping in low power operation:
391. Keep track of elapsed time in low power mode only when ThreadX timers are active. If there are ThreadX timers active, the elapsed time while in low power mode must be measured, thus a low power hardware timer is required (this timer can be configured in **TX_LOW_POWER_TIMER_SETUP**). If there are no ThreadX timers active when entering low power mode, then no hardware timer needs to keep track of elapsed time. This is "tick-less" operation. To enable this feature, the symbol **TX_LOW_POWER_TICKLESS** must be defined. The internal ThreadX tick count will not reflect the time spent in low power mode when no ThreadX timers are active.
402. Always keep track of time in low power mode. This is necessary to keep the internal ThreadX tick count accurate. In this case, **TX_LOW_POWER_TICKLESS** must *not* be defined, as a hardware timer will always be needed in low power mode to measure elapsed time. The hardware timer is intended to be configured in **TX_LOW_POWER_TIMER_SETUP**.
41
42> Example 1: No low power timer is in use (**TX_LOW_POWER_TIMER_SETUP** is *not* defined). There is a ThreadX timer with 50 ticks remaining. The internal ThreadX tick count is 1000. The processor goes into low power mode for some length of time. After exiting low power mode, the ThreadX timer still has 50 ticks remaining. The internal ThreadX tick count is 1000.
43
44> Example 2: A low power timer is available (**TX_LOW_POWER_TIMER_SETUP** is defined). **TX_LOW_POWER_TICKLESS** is defined. There is a ThreadX timer A with 50 ticks remaining and another ThreadX timer B with 20 ticks remaining. The internal ThreadX tick count is 1000. The processor goes into low power mode for 20 ticks. Upon exiting low power mode, the ThreadX timer A will have 30 ticks remaining. The expiration function for ThreadX timer B will be executed. The internal ThreadX tick count is 1020.
45After executing for some time, the internal ThreadX tick count is 2000 and there are no ThreadX timers active. The processor goes into low power mode for some length of time. After exiting low power mode, the internal ThreadX tick count is 2000.
46
47> Example 3: A low power timer is always used (**TX_LOW_POWER_TIMER_SETUP** is defined and **TX_LOW_POWER_TICKLESS** is *not* defined). The internal ThreadX tick count is 1000 and there are no ThreadX timers active. The processor goes into low power mode for some length of time. Upon exiting low power mode, it is determined that the processor was in low power mode for 20 ticks. The internal ThreadX tick count is updated to 1020.
48
49## User-defined Macros
50
51The following macros invoke functions that the user may want to define/implement.
52
53### Summary of user-defined macros
54
55 - ```TX_LOW_POWER_TIMER_SETUP``` - *set up low power timer*
56 - ```TX_LOW_POWER_USER_ENTER``` - *configure processor to enter low power mode*
57 - ```TX_LOW_POWER_USER_EXIT``` - *configure processor to exit low power mode*
58 - ```TX_LOW_POWER_USER_TIMER_ADJUST``` - *return the number of ticks the processor was in low power mode*
59
60---
61
62### TX_LOW_POWER_TIMER_SETUP
63```c
64VOID TX_LOW_POWER_TIMER_SETUP(ULONG tx_low_power_next_expiration);
65```
66
67### Input parameters
68
69- *tx_low_power_next_expiration* - the number of ticks to configure the low power timer.
70
71### Return values
72
73- *none*
74
75**TX_LOW_POWER_TIMER_SETUP** is a macro invoking user-defined function that sets up a low power timer. To set up a low power timer or operate ticklessly in low power mode, this symbol must be defined. This macro is called in ```tx_low_power_enter```. If **TX_LOW_POWER_TICKLESS** is not defined and there are no timers active, the *tx_low_power_next_expiration* parameter will be set to 0xFFFFFFFF.
76
77> Note: The number of ThreadX ticks is the input to this function. The frequency of a ThreadX timer tick is defined in **TX_TIMER_TICKS_PER_SECOND** (typically defined in file tx_api.h, tx_user.h, or tx_port.h).
78
79> Note: do not put the processor to sleep in this macro.
80
81### Optional Define
82
83- **TX_LOW_POWER_TICKLESS** - an optional define to operate ticklessly in low power mode only if no ThreadX timers are active. With symbol **TX_LOW_POWER_TICKLESS** defined, if there are no ThreadX timers active, **TX_LOW_POWER_TIMER_SETUP** will not be called in ```tx_low_power_enter```. ThreadX will not maintain/update the internal tick count during or after exiting low power mode. Symbol **TX_LOW_POWER_TIMER_SETUP** must also be defined if defining **TX_LOW_POWER_TICKLESS**.
84
85### Example
86
87```c
88/* Low power timer function prototype. */
89void low_power_timer_config(ULONG ticks);
90
91/* Define the TX_LOW_POWER_TIMER_SETUP macro. */
92#define TX_LOW_POWER_TIMER_SETUP low_power_timer_config
93
94void low_power_timer_config(ULONG ticks)
95{
96    /* Insert code here to configure a hardware timer
97       to wake the processor from sleep after
98       ticks/TX_TIMER_TICKS_PER_SECOND seconds. */
99}
100```
101
102---
103
104### TX_LOW_POWER_USER_ENTER
105A macro invoking a user-defined function that configures the processor for entering low power mode (e.g. turn off peripherals and select a sleep mode). This macro is called in ```tx_low_power_enter```.
106
107### Input parameters
108
109- *none*
110
111### Return values
112
113- *none*
114
115### Example
116
117```c
118/* Low power enter function prototype. */
119void low_power_enter(void);
120
121/* Define the TX_LOW_POWER_USER_ENTER macro. */
122#define TX_LOW_POWER_USER_ENTER low_power_enter
123
124void low_power_enter(void)
125{
126    /* Insert code here to configure the processor to enter low power mode. */
127}
128```
129---
130
131### TX_LOW_POWER_USER_EXIT
132A macro invoking a user-defined function that configures the processor for exiting low power mode (e.g. turn on peripherals). This is called in ```tx_low_power_exit```.
133
134### Input parameters
135
136- *none*
137
138### Return values
139
140- *none*
141
142### Example
143
144```c
145/* Low power exit function prototype. */
146void low_power_exit(void);
147
148/* Define the TX_LOW_POWER_USER_EXIT macro. */
149#define TX_LOW_POWER_USER_EXIT low_power_exit
150
151void low_power_exit(void)
152{
153    /* Insert code here to configure the processor to exit low power mode. */
154}
155```
156
157---
158
159### TX_LOW_POWER_USER_TIMER_ADJUST
160
161```c
162ULONG TX_LOW_POWER_USER_TIMER_ADJUST(VOID);
163```
164
165A macro invoking a user-defined function to determine how much time has elapsed while in low power mode (in units of ThreadX ticks). This is called in ```tx_low_power_exit``` and returns the number of ticks needed to adjust the ThreadX timers.
166
167When exiting low power mode, there are two possibilities:
168 1. The processor slept for the entire time the timer was configured to sleep.
169 2. The processor was awakened early.
170
171### Input parameters
172
173- *none*
174
175### Return values
176
177- *tx_low_power_adjust_ticks*
178
179### Example
180
181```c
182/* Low power timer adjust function prototype. */
183ULONG low_power_timer_adjust(void);
184
185/* Define the TX_LOW_POWER_USER_TIMER_ADJUST macro. */
186#define TX_LOW_POWER_USER_TIMER_ADJUST low_power_timer_adjust
187
188ULONG low_power_timer_adjust(void)
189{
190    ULONG actual_ticks_slept;
191    ULONG elapsed_time_in_ms;
192
193    /* Insert code here to read timer registers to determine
194       how long the processor actually slept. */
195    elapsed_time_in_ms = read_timer_register();
196
197    /* Convert elapsed time to ThreadX ticks. */
198    actual_ticks_slept = elapsed_time_in_ms / (1000/TX_TIMER_TICKS_PER_SECOND);
199
200    return(actual_ticks_slept);
201}
202```
203
204---
205
206## Summary of Low Power APIs
207
208- ```tx_low_power_enter``` - *Enter low power mode*
209- ```tx_low_power_exit``` - *Exit low power mode*
210- ```tx_time_increment``` - *Increment ThreadX timers by specific amount*
211- ```tx_timer_get_next``` - *Get next ThreadX timer expiration*
212
213---
214
215## tx_low_power_enter
216
217Enter low power mode.
218
219### Prototype
220
221```c
222VOID tx_low_power_enter(VOID);
223```
224
225### Description
226
227This service enters low power mode. The macros **TX_LOW_POWER_TIMER_SETUP** and **TX_LOW_POWER_USER_ENTER** are called in this function to allow the user to configure a low power timer and configure the hardware for low power mode.
228
229For keeping track of time while in low power mode, there are two possibilities:
230
2311. A ThreadX timer is active. Function ```tx_timer_get_next``` returns **TX_TRUE**. Note that in this situation, a low power clock must be used in order to wake up the CPU for the next ThreadX timer expiration. Therefore a low power timer/clock must be programmed. Program the hardware timer source such that the next timer interrupt is equal to: *tx_low_power_next_expiration \* tick_frequency*. The *tick_frequency* is application-specific and typically set up in ```tx_low_level_initialize```.
232
2332. There are no ThreadX timers active. Function ```tx_timer_get_next``` returns *TX_FALSE*.
234    1. The application may choose **not** to keep the ThreadX internal
235   tick count updated (define **TX_LOW_POWER_TICKLESS**), therefore there is no need to set up a low power clock.
236    2. The application still needs to keep the ThreadX tick up-to-date. In this case a low power clock needs to be configured.
237
238### Input parameters
239
240- *none*
241
242### Return values
243
244- *none*
245
246### Allowed from
247
248Internal ThreadX code, application
249
250### Example
251
252ARM Cortex-M assembly
253```c
254#ifdef TX_LOW_POWER
255    PUSH    {r0-r3}
256    BL      tx_low_power_enter                      // Enter low power mode
257    POP     {r0-r3}
258#endif
259
260#ifdef TX_ENABLE_WFI
261    DSB                                             // Ensure no outstanding memory transactions
262    WFI                                             // Wait for interrupt
263    ISB                                             // Ensure pipeline is flushed
264#endif
265
266#ifdef TX_LOW_POWER
267    PUSH    {r0-r3}
268    BL      tx_low_power_exit                       // Exit low power mode
269    POP     {r0-r3}
270#endif
271```
272### See also
273
274- tx_low_power_exit
275
276---
277
278## tx_low_power_exit
279
280Exit low power mode.
281
282### Prototype
283
284```c
285VOID tx_low_power_exit(VOID);
286
287```
288
289### Description
290
291This service exits low power mode. Macro **TX_LOW_POWER_USER_EXIT** is called in this function to allow the user to configure the hardware to exit low power mode. Macro **TX_LOW_POWER_USER_TIMER_ADJUST** is called in this function to determine how long the processor actually slept.
292
293### Input parameters
294
295- *none*
296
297### Return values
298
299- *none*
300
301### Allowed from
302
303Internal ThreadX code, application
304
305### Example
306
307```c
308#ifdef TX_LOW_POWER
309    PUSH    {r0-r3}
310    BL      tx_low_power_enter                      // Enter low power mode
311    POP     {r0-r3}
312#endif
313
314#ifdef TX_ENABLE_WFI
315    DSB                                             // Ensure no outstanding memory transactions
316    WFI                                             // Wait for interrupt
317    ISB                                             // Ensure pipeline is flushed
318#endif
319
320#ifdef TX_LOW_POWER
321    PUSH    {r0-r3}
322    BL      tx_low_power_exit                       // Exit low power mode
323    POP     {r0-r3}
324#endif
325```
326
327### See also
328
329- tx_low_power_enter
330
331---
332
333## tx_time_increment
334
335This function increments the current time by a specified value. The value was derived by the application by calling the ```tx_timer_get_next``` function prior to this call, which was right before the processor was put in low power mode.
336
337### Prototype
338
339```c
340VOID tx_time_increment(ULONG time_increment);
341```
342
343### Description
344
345This function increments the current time by a specified value. The value was derived by the application by calling the ```tx_timer_get_next``` function prior to this call, which was right before the processor was put in low power mode.
346
347### Input parameters
348
349- *time_increment* - Number of ThreadX ticks to increment time and timers.
350
351### Return values
352
353- *none*
354
355### Allowed from
356
357Internal ThreadX code, application
358
359### Example
360
361From ```tx_low_power_exit```:
362
363```c
364        /* Call the low-power timer driver code to obtain the amount of time (in ticks)
365        the system has been in low power mode. */
366#ifdef TX_LOW_POWER_TIMER_ADJUST
367        tx_low_power_adjust_ticks = TX_LOW_POWER_USER_TIMER_ADJUST;
368#else
369        tx_low_power_adjust_ticks = (ULONG) 0;
370#endif
371
372        /* Determine if the ThreadX timer needs incrementing.  */
373        if (tx_low_power_adjust_ticks)
374        {
375            /* Yes, the ThreadX time must be incremented.  */
376            tx_time_increment(tx_low_power_adjust_ticks);
377        }
378```
379
380### See also
381
382- tx_timer_get_next
383
384---
385
386## tx_timer_get_next
387
388Get next ThreadX timer expiration
389
390### Prototype
391
392```c
393ULONG tx_timer_get_next(ULONG *next_timer_tick_ptr);
394```
395
396### Description
397
398This service gets the next ThreadX timer expiration, in ticks.
399
400### Input parameters
401
402- *next_timer_tick_ptr* - pointer to hold number of ticks
403
404### Return values
405
406- *TX_TRUE* (1) At least one timer is active.
407- *TX_FALSE* (0) No timers are currently active.
408
409### Allowed from
410
411Internal ThreadX code, application
412
413### Example
414
415From ```tx_low_power_enter```:
416
417```c
418ULONG   tx_low_power_next_expiration;   /* The next timer expiration (units of ThreadX timer ticks). */
419ULONG   timers_active;
420
421    /*  At this point, we want to enter low power mode, since nothing
422        meaningful is going on in the system. However, in order to keep
423        the ThreadX timer services accurate, we must first determine the
424        next ThreadX timer expiration in terms of ticks. This is
425        accomplished via the tx_timer_get_next API.  */
426    timers_active =  tx_timer_get_next(&tx_low_power_next_expiration);
427```
428
429### See also
430
431- tx_time_increment
432