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