1@page page_device_hwtimer HWTIMER Device 2 3# Introduction to the Timer 4 5Hardware timers generally have two modes of operation, timer mode and counter mode. No matter which mode is operated, it works by counting the pulse signal counted by the internal counter module. Here are some important concepts of timers. 6 7**Timer mode**: Counts the internal pulse. Timers are often used as timing clocks for timing detection, timing response, and timing control. 8 9**Counter mode**: The counter can count up or down. The maximum count value of a 16-bit counter is 65535, and the maximum value of a 32-bit counter is 4 294 967 295. 10 11**Counting frequency**:Since the input frequency is usually fixed, the time it takes for the counter to reach its desired count number can be calculated from just the given frequency - `time = count value / count frequency`. For example, if the counting frequency is 1 MHz, the counter counts once every 1 / 1000000 seconds. That is, every 1 microsecond, the counter is incremented by one (or subtracted by one), at this time, the maximum timing capability of the 16-bit counter is 65535 microseconds, or 65.535 milliseconds. 12 13# Access Hardware Timer Device 14 15The application accesses the hardware timer device through the I/O device management interface provided by RT-Thread. The related interfaces are as follows: 16 17| **Function** | **Description** | 18| -------------------- | ---------------------------------- | 19| rt_device_find() | to look up the timer device | 20| rt_device_open() | to open the timer device in read-write mode | 21| rt_device_set_rx_indicate() | to set the timeout callback function | 22| rt_device_control() | to control the timer device, you can set the timing mode (single time /cycle),counting frequency, or stop the timer | 23| rt_device_write() | to set the timeout value of the timer. The timer then starts | 24| rt_device_read() | to get the current value of the timer | 25| rt_device_close() | to turn off the timer device. | 26 27## Find Timer Device 28 29The application obtains the device handle based on the hardware timer device name, and thus can operate the hardware timer device. The device function is as follows: 30 31```c 32rt_device_t rt_device_find(const char* name); 33``` 34 35| Parameter | **Description** | 36| -------- | ---------------------------------- | 37| name | hardware timer device name | 38| **return** | —— | 39| timer device handle | will return to the corresponding device handle if the corresponding device is found | 40| RT_NULL | No device found | 41 42In general, the hardware timer device name registered to the system is timer0, timer1, etc. The usage examples are as follows: 43 44```c 45#define HWTIMER_DEV_NAME "timer0" /* timer name */ 46rt_device_t hw_dev; /* timer device handle */ 47/* find timer device */ 48hw_dev = rt_device_find(HWTIMER_DEV_NAME); 49``` 50 51## Open Timer Device 52 53With the device handle, the application can open the device. When the device is open, it will detect whether the device has been initialized. If it is not initialized, it will call the initialization interface to initialize the device by default. Open the device with the following function: 54 55```c 56rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags); 57``` 58 59| Parameter | Description | 60| ---------- | ------------------------------- | 61| dev | hardware timer device handle | 62| oflags | device open mode, is generally opened in read and write mode, which is to take the value:RT_DEVICE_OFLAG_RDWR | 63| **return** | —— | 64| RT_EOK | device opened successfully | 65| other error code | device fail to open | 66 67An example of use is as follows: 68 69```c 70#define HWTIMER_DEV_NAME "timer0" /* timer name */ 71rt_device_t hw_dev; /* timer device handle */ 72/* find timer device */ 73hw_dev = rt_device_find(HWTIMER_DEV_NAME); 74/* to open the timer device in read-write mode */ 75rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 76``` 77 78## Set the Timeout Callback Function 79 80Set the timer timeout callback function with the following function - this is the function that will be called when the timer reaches its set count value: 81 82```c 83rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size)) 84``` 85 86| Parameter | **Description** | 87| ---------- | ------------------------------- | 88| dev | device handle | 89| rx_ind | timeout callback function, provided by the caller | 90| **return** | —— | 91| RT_EOK | success | 92 93An example of use is as follows: 94 95```c 96#define HWTIMER_DEV_NAME "timer0" /* timer name */ 97rt_device_t hw_dev; /* timer device handle */ 98 99/* timer timeout callback function */ 100static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) 101{ 102 rt_kprintf("this is hwtimer timeout callback fucntion!\n"); 103 rt_kprintf("tick is :%d !\n", rt_tick_get()); 104 105 return 0; 106} 107 108static int hwtimer_sample(int argc, char *argv[]) 109{ 110 /* find timer device */ 111 hw_dev = rt_device_find(HWTIMER_DEV_NAME); 112 /* open the device in read and write mode */ 113 rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 114 /* set the timeout callback function */ 115 rt_device_set_rx_indicate(hw_dev, timeout_cb); 116} 117``` 118 119## Control the Timer Device 120 121By sending control words, the application can configure the hardware timer device with the following function: 122 123```c 124rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg); 125``` 126 127| Parameter | **Description** | 128| ---------------- | ------------------------------ | 129| dev | device handle | 130| cmd | command control word | 131| arg | controlled parameter | 132| **return** | —— | 133| RT_EOK | function executed successfully | 134| -RT_ENOSYS | execution failed,dev is null | 135| other error code | execution failed | 136 137The command control words available for the hardware timer device are as follows: 138 139| **Control word** | Description | 140| ---------------------- | ------------------------ | 141| HWTIMER_CTRL_FREQ_SET | set the counting frequency | 142| HWTIMER_CTRL_STOP | stop the timer | 143| HWTIMER_CTRL_INFO_GET | get timer feature information | 144| HWTIMER_CTRL_MODE_SET | set timer mode | 145 146Get the timer parameter argument, which is a pointer to the structure struct rt_hwtimer_info, to save the obtained information. 147 148>Setting frequency is valid only when the timer hardware and included driver set the counting frequency. Generally, the default frequency of the driving setting can be used. 149 150When setting the timer mode, the parameter argument can take the following values: 151 152```c 153HWTIMER_MODE_ONESHOT /* Single timing */ 154HWTIMER_MODE_PERIOD /* Periodic timing */ 155``` 156 157An example of using the timer count frequency and timing mode is as follows: 158 159```c 160#define HWTIMER_DEV_NAME "timer0" /* timer name */ 161rt_device_t hw_dev; /* timer device handle */ 162rt_hwtimer_mode_t mode; /* timer mode */ 163rt_uint32_t freq = 10000; /* couting frequency */ 164 165/* Timer timeout callback function */ 166static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) 167{ 168 rt_kprintf("this is hwtimer timeout callback fucntion!\n"); 169 rt_kprintf("tick is :%d !\n", rt_tick_get()); 170 171 return 0; 172} 173 174static int hwtimer_sample(int argc, char *argv[]) 175{ 176 /* find timer device */ 177 hw_dev = rt_device_find(HWTIMER_DEV_NAME); 178 /* open the device in read and write mode */ 179 rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 180 /* Set the timeout callback function */ 181 rt_device_set_rx_indicate(hw_dev, timeout_cb); 182 183 /* Set the counting frequency (1Mhz or the supported minimum counting frequency by default) */ 184 rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq); 185 /* Set the mode to periodic timer */ 186 mode = HWTIMER_MODE_PERIOD; 187 rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode); 188} 189``` 190 191## Set the Timer Timeout Value 192 193The timer timeout value can be set by the following function: 194 195```c 196rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size); 197``` 198 199| **Parameter** | Description | 200| ---------- | ------------------------------------------ | 201| dev | device handle | 202| pos | write data offset, unused now, can set 0 value | 203| buffer | pointer to the timer timeout structure | 204| size | timeout structure size | 205| **return** | —— | 206| The actual size of the written data | | 207| 0 | fail | 208 209The prototype of the timeout structure is shown below : 210 211```c 212typedef struct rt_hwtimerval 213{ 214 rt_int32_t sec; /* second */ 215 rt_int32_t usec; /* microsecond */ 216} rt_hwtimerval_t; 217``` 218 219An example of using the timer timeout value is as follows: 220 221```c 222#define HWTIMER_DEV_NAME "timer0" /* timer name */ 223rt_device_t hw_dev; /* timer device handle */ 224rt_hwtimer_mode_t mode; /* timer mode */ 225rt_hwtimerval_t timeout_s; /* Timer timeout value */ 226 227/* Timer timeout callback function */ 228static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) 229{ 230 rt_kprintf("this is hwtimer timeout callback fucntion!\n"); 231 rt_kprintf("tick is :%d !\n", rt_tick_get()); 232 233 return 0; 234} 235 236static int hwtimer_sample(int argc, char *argv[]) 237{ 238 /* find timer device */ 239 hw_dev = rt_device_find(HWTIMER_DEV_NAME); 240 /* open the device in read-write mode */ 241 rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 242 /* set the timeout callback function */ 243 rt_device_set_rx_indicate(hw_dev, timeout_cb); 244 /* set the mode as periodic timer */ 245 mode = HWTIMER_MODE_PERIOD; 246 rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode); 247 248 /* Set the timer timeout value to 5s and start the timer */ 249 timeout_s.sec = 5; /* second */ 250 timeout_s.usec = 0; /* microsecond */ 251 rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)); 252} 253``` 254 255## Obtain the Current Value of the Timer 256 257The current value of the timer can be obtained by the following function: 258 259```c 260rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size); 261``` 262 263| **Parameter** | Description | 264| ---------- | ------------------------------------------ | 265| dev | timer device handle | 266| pos | write data offset, unused now , can set 0 value | 267| buffer | output parameter, a pointer point to the timeout structure | 268| size | timeout structure size | 269| **return** | —— | 270| Timeout structure size | success | 271| 0 | fail | 272 273An example of use is shown below: 274 275```c 276rt_hwtimerval_t timeout_s; /* Used to save the time the timer has elapsed */ 277/* Read the elapsed time of the timer */ 278rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s)); 279``` 280 281## Close the Timer Device 282 283The timer device can be closed with the following function: 284 285```c 286rt_err_t rt_device_close(rt_device_t dev); 287``` 288 289| Parameter | Description | 290| ---------- | ---------------------------------- | 291| dev | timer device handle | 292| **return** | —— | 293| RT_EOK | close device successfully | 294| -RT_ERROR | the device has been completely shut down and cannot be closed repeatedly | 295| other error code | fail to close the device | 296 297When a timer device has been used and is not necessary anymore, it should be closed, otherwise the device will remain in an open status. 298 299 An example of use is shown below: 300 301```c 302#define HWTIMER_DEV_NAME "timer0" /* timer name */ 303rt_device_t hw_dev; /* timer device handle */ 304/* find timer device */ 305hw_dev = rt_device_find(HWTIMER_DEV_NAME); 306... ... 307rt_device_close(hw_dev); 308``` 309 310>Timing errors may occur. Assume that the counter has a maximum value of 0xFFFF, a counting frequency of 1Mhz, and a timing time of 1 second and 1 microsecond. Since the timer can only count up to 65535us at a time, the timing requirement for 1000001us can be completed 20 times at 50000us, and the calculation error will be 1us. 311 312# Hardware Timer Device Usage Example 313 314The specific use of the hardware timer device can refer to the following sample code. The main steps of the sample code are as follows: 315 3161. First find the device handle based on the timer device name "timer0". 3172. Open the device "timer0" in read-write mode. 3183. Set the timer timeout callback function. 3194. Set the timer mode to periodic timer and set the timeout period to 5 seconds. At this time, the timer starts. 3205. Read the timer after 3500ms delay, the read value will be displayed in seconds and microseconds. 321 322```c 323 /* 324 * Program listing: This is an hwtimer device usage routine 325 * The routine exports the hwtimer_sample command to the control terminal 326 * Command call format: hwtimer_sample 327 * Program function: The hardware timer timeout callback function periodically prints the current tick value, and the difference between the two tick values is converted to the time equivalent to the timing time value. 328 */ 329 330#include <rtthread.h> 331#include <rtdevice.h> 332 333#define HWTIMER_DEV_NAME "timer0" /* timer name */ 334 335/* Timer timeout callback function */ 336static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) 337{ 338 rt_kprintf("this is hwtimer timeout callback fucntion!\n"); 339 rt_kprintf("tick is :%d !\n", rt_tick_get()); 340 341 return 0; 342} 343 344static int hwtimer_sample(int argc, char *argv[]) 345{ 346 rt_err_t ret = RT_EOK; 347 rt_hwtimerval_t timeout_s; /* timer timeout value */ 348 rt_device_t hw_dev = RT_NULL; /* timer device value */ 349 rt_hwtimer_mode_t mode; /* timer mode */ 350 351 /* find timer device */ 352 hw_dev = rt_device_find(HWTIMER_DEV_NAME); 353 if (hw_dev == RT_NULL) 354 { 355 rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME); 356 return -RT_ERROR; 357 } 358 359 /* Open the device in read-write mode */ 360 ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); 361 if (ret != RT_EOK) 362 { 363 rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME); 364 return ret; 365 } 366 367 /* set timeout callback function */ 368 rt_device_set_rx_indicate(hw_dev, timeout_cb); 369 370 /* Setting mode is periodic timer */ 371 mode = HWTIMER_MODE_PERIOD; 372 ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode); 373 if (ret != RT_EOK) 374 { 375 rt_kprintf("set mode failed! ret is :%d\n", ret); 376 return ret; 377 } 378 379 /* Set the timer timeout value to 5s and start the timer. */ 380 timeout_s.sec = 5; /* second */ 381 timeout_s.usec = 0; /* microsecond */ 382 383 if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s)) 384 { 385 rt_kprintf("set timeout value failed\n"); 386 return -RT_ERROR; 387 } 388 389 /* delay 3500ms */ 390 rt_thread_mdelay(3500); 391 392 /* read the current value of timer */ 393 rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s)); 394 rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec); 395 396 return ret; 397} 398/* Export to the msh command list */ 399MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample); 400``` 401