• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Software Timer
2
3
4## Basic Concepts
5
6The software timer is a software-simulated timer based on system tick interrupts. When the preset tick counter value has elapsed, the user-defined callback will be invoked. The timing precision is related to the cycle of the system tick clock.
7
8Due to the limitation in hardware, the number of hardware timers cannot meet users' requirements. Therefore, the OpenHarmony LiteOS-M kernel provides the software timer function. The software timer allows more timing services to be created, increasing the number of timers.
9
10The software timer supports the following functions:
11
12- Disabling the software timer using a macro
13
14- Creating a software timer
15
16- Starting a software timer
17
18- Stopping a software timer
19
20- Deleting a software timer
21
22- Obtaining the number of remaining ticks of a software timer
23
24
25## Working Principles
26
27The software timer is a system resource. When modules are initialized, a contiguous section of memory is allocated for software timers. The maximum number of timers supported by the system is configured by the **LOSCFG_BASE_CORE_SWTMR_LIMIT** macro in **los_config.h**.
28
29Software timers use a queue and a task resource of the system. The software timers are triggered based on the First In First Out (FIFO) rule. A timer with a shorter value is always closer to the queue head than a timer with a longer value, and is preferentially triggered.
30
31The software timer counts time in ticks. When a software timer is created and started, the OpenHarmony LiteOS-M kernel determines the timer expiry time based on the current system time (in ticks) and the timing interval set by the user, and adds the timer control structure to the global timing list.
32
33When a tick interrupt occurs, the tick interrupt handler scans the global timing list for expired timers. If such timers are found, the timers are recorded.
34
35When the tick interrupt handler is complete, the software timer task (with the highest priority) will be woken up. In this task, the timeout callback for the recorded timer is called.
36
37
38### Timer States
39
40- OS_SWTMR_STATUS_UNUSED
41  The timer is not in use. When the timer module is initialized, all timer resources in the system are set to this state.
42
43- OS_SWTMR_STATUS_CREATED
44  The timer is created but not started or the timer is stopped. When **LOS_SwtmrCreate** is called for a timer that is not in use or **LOS_SwtmrStop** is called for a newly started timer, the timer changes to this state.
45
46- OS_SWTMR_STATUS_TICKING
47  The timer is running (counting). When **LOS_SwtmrStart** is called for a newly created timer, the timer enters this state.
48
49
50### Timer Modes
51
52The OpenHarmony LiteOS-M kernel provides the following types of software timers:
53
54- One-shot timer: Once started, the timer is automatically deleted after triggering only one timer event.
55
56- Periodic timer: This type of timer periodically triggers timer events until it is manually stopped.
57
58- One-shot timer deleted by calling an API
59
60
61## Available APIs
62
63The following table describes APIs available for the OpenHarmony LiteOS-M software timer module. For more details about the APIs, see the API reference.
64
65**Table 1** Software timer APIs
66
67| Category| Description|
68| -------- | -------- |
69| Creating or deleting a timer| **LOS_SwtmrCreate**: creates a timer.<br>**LOS_SwtmrDelete**: deletes a timer.|
70| Starting or stopping a timer| **LOS_SwtmrStart**: starts a timer.<br>**LOS_SwtmrStop**: Stops a timer.|
71| Obtaining remaining ticks of a software timer| **LOS_SwtmrTimeGet**: obtains the remaining ticks of a software timer.|
72
73
74## How to Develop
75
76The typical development process of software timers is as follows:
77
781. Configure the software timer.
79   - Check that **LOSCFG_BASE_CORE_SWTMR** and **LOSCFG_BASE_IPC_QUEUE** are set to **1**.
80   - Configure **LOSCFG_BASE_CORE_SWTMR_LIMIT** (maximum number of software timers supported by the system).
81   - Configure **OS_SWTMR_HANDLE_QUEUE_SIZE** (maximum length of the software timer queue).
82
832. Call **LOS_SwtmrCreate** to create a software timer.
84   - Create a software timer with the specified timing duration, timeout handling function, and triggering mode.
85   - Return the function execution result (success or failure).
86
873. Call **LOS_SwtmrStart** to start the software timer.
88
894. Call **LOS_SwtmrTimeGet** to obtain the remaining number of ticks of the software timer.
90
915. Call **LOS_SwtmrStop** to stop the software timer.
92
936. Call **LOS_SwtmrDelete** to delete the software timer.
94
95> **NOTE**
96> - Avoid too many operations in the callback of the software timer. Do not use APIs or perform operations that may cause task suspension or blocking.
97>
98> - The software timers use a queue and a task resource of the system. The priority of the software timer tasks is set to **0** and cannot be changed.
99>
100> - The number of software timer resources that can be configured in the system is the total number of software timer resources available to the entire system, not the number of software timer resources available to users. For example, if the system software timer occupies one more resource, the number of software timer resources available to users decreases by one.
101>
102> - If a one-shot software timer is created, the system automatically deletes the timer and reclaims resources after the timer times out and the callback is invoked.
103>
104> - For a one-shot software timer that will not be automatically deleted after expiration, you need to call **LOS_SwtmrDelete** to delete it and reclaim the timer resource to prevent resource leakage.
105
106
107## Development Example
108
109
110### Example Description
111
112The following programming example demonstrates how to:
113
1141. Create, start, delete, pause, and restart a software timer.
115
1162. Use a one-shot software timer and a periodic software timer
117
118
119### Sample Code
120
121**Prerequisites**
122
123- In **los_config.h**, **LOSCFG_BASE_CORE_SWTMR** is enabled.
124
125- In **los_config.h**, **LOSCFG_BASE_CORE_SWTMR_ALIGN** is disabled. The sample code does not involve timer alignment.
126
127- The maximum number of software timers supported by the system (**LOSCFG_BASE_CORE_SWTMR_LIMIT**) is configured.
128
129- The maximum length of the software timer queue (OS_SWTMR_HANDLE_QUEUE_SIZE) is configured.
130
131The sample code is as follows:
132
133The sample code is compiled and verified in **./kernel/liteos_m/testsuites/src/osTest.c**. Call **ExampleSwtmr** in **TestTaskEntry**.
134
135
136```
137#include "los_swtmr.h"
138
139/* Timer interval. */
140#define SWTMR_INTERVAL_LONG      1000
141#define SWTMR_INTERVAL_SHORT     100
142
143/* Number of times that the timers are triggered. */
144UINT32 g_timerCount1 = 0;
145UINT32 g_timerCount2 = 0;
146
147/* Callback 1, for the one-shot software timer. */
148void Timer1Callback(UINT32 arg)
149{
150    g_timerCount1++;
151    printf("g_timerCount1=%d\n", g_timerCount1);
152}
153
154/* Callback 2, for the periodic software timer. */
155void Timer2Callback(UINT32 arg)
156{
157    g_timerCount2++;
158    printf("g_timerCount2=%d\n", g_timerCount2);
159}
160
161void SwtmrTest(void)
162{
163    UINT32 ret;
164    UINT32 id1; // One-shot software timer.
165    UINT32 id2; // Periodic software timer.
166    UINT32 tickCount;
167
168#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
169    /* Create a one-shot software timer, with the number of ticks set to 1000. Invoke callback 1 when the number of ticks reaches 1000. */
170    LOS_SwtmrCreate(SWTMR_INTERVAL_LONG, LOS_SWTMR_MODE_ONCE, Timer1Callback, &id1, 0,
171                    OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_SENSITIVE);
172
173    /* Create a periodic software timer and invoke callback 2 every 100 ticks. */
174    LOS_SwtmrCreate(SWTMR_INTERVAL_SHORT, LOS_SWTMR_MODE_PERIOD, Timer2Callback, &id2, 0,
175                    OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_SENSITIVE);
176#else
177    /* Create a one-shot software timer, with the number of ticks set to 1000. Callback 1 will be invoked when the number of ticks reaches 1000. */
178    LOS_SwtmrCreate(SWTMR_INTERVAL_LONG, LOS_SWTMR_MODE_ONCE, Timer1Callback, &id1, 0);
179
180    /* Create a periodic software timer and invoke callback 2 every 100 ticks. */
181    LOS_SwtmrCreate(SWTMR_INTERVAL_SHORT, LOS_SWTMR_MODE_PERIOD, Timer2Callback, &id2, 0);
182#endif
183
184    /* Start the one-time software timer. */
185    ret = LOS_SwtmrStart(id1);
186    printf("start Timer1 %s\n", (ret == LOS_OK) ? "success" : "failed");
187
188    /* Short delay. The timer is not triggered yet. */
189    LOS_TaskDelay(SWTMR_INTERVAL_SHORT);
190
191    /* The one-short timer is not triggered yet. The timer can be stopped successfully. */
192    ret = LOS_SwtmrStop(id1);
193    printf("stop timer1 %s\n", (ret == LOS_OK) ? "success" : "failed");
194
195    LOS_SwtmrStart(id1);
196
197    /* Long-time delay, triggered by the timer. */
198    LOS_TaskDelay(SWTMR_INTERVAL_LONG);
199
200    /* The timer is automatically deleted after being triggered. The stop operation should fail. */
201    ret = LOS_SwtmrStop(id1);
202    printf("timer1 self delete test %s\n", (ret != LOS_OK) ? "success" : "failed");
203
204    /* Start the periodic software timer. */
205    ret = LOS_SwtmrStart(id2);
206    printf("start Timer2 %s\n", (ret == LOS_OK) ? "success" : "failed");
207
208    /* Long-time delay, triggered periodically by the timer. */
209    LOS_TaskDelay(SWTMR_INTERVAL_LONG);
210
211    LOS_SwtmrStop(id2);
212
213    ret = LOS_SwtmrDelete(id2);
214    if (ret == LOS_OK) {
215        printf("delete Timer2 success\n");
216    }
217}
218
219UINT32 ExampleSwtmr(VOID)
220{
221    UINT32 ret;
222    TSK_INIT_PARAM_S taskParam = { 0 };
223    UINT32 taskId;
224
225    /* Lock task scheduling. */
226    LOS_TaskLock();
227
228    /* Create a task. */
229    taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SwtmrTest;
230    taskParam.pcName       = "TimerTsk";
231    taskParam.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
232    taskParam.usTaskPrio   = 5;
233    ret = LOS_TaskCreate(&taskId, &taskParam);
234    if (ret != LOS_OK) {
235        printf("TimerTsk create failed.\n");
236        return LOS_NOK;
237    }
238
239    /* Unlock task scheduling. */
240    LOS_TaskUnlock();
241    return LOS_OK;
242}
243```
244
245
246### Verification
247
248The output is as follows:
249
250
251```
252start Timer1 success
253stop timer1 success
254g_timerCount1=1
255timer1 self delete test success
256start Timer2 success
257g_timerCount2=1
258g_timerCount2=2
259g_timerCount2=3
260g_timerCount2=4
261g_timerCount2=5
262g_timerCount2=6
263g_timerCount2=7
264g_timerCount2=8
265g_timerCount2=9
266g_timerCount2=10
267delete Timer2 success
268```
269