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