Skip to content

Commit 94786f8

Browse files
authored
Merge pull request #84 from Lawlieta/master
【添加】machine.WDT 模块和 machine.Timer 模块
2 parents adcf566 + 8203c6b commit 94786f8

File tree

9 files changed

+531
-1
lines changed

9 files changed

+531
-1
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
## machine.WDT
2+
3+
**machine.WDT** 类是 machine 模块下的一个硬件类,用于 WDT 设备的配置和控制,提供对 WDT 设备的操作方法。
4+
5+
如下为 WDT 设备基本介绍:
6+
7+
- WDT(WatchDog Timer,硬件看门狗),是一个定时器设备,用于系统程序结束或出错导致系统进入不可恢复状态时重启系统。
8+
9+
- WDT 启动之后,计数器开始计数,在计数器溢出前没有被复位,会对 CPU 产生一个复位信号使设备重启(简称 “被狗咬”);
10+
11+
- 系统正常运行时,需要在 WDT 设备允许的时间间隔内对看门狗计数清零(简称“喂狗”),WDT 设备一旦启动,需要定时“喂狗”以确保设备正常运行。
12+
13+
### 构造函数
14+
15+
在 RT-Thread MicroPython 中 `WDT` 对象的构造函数如下:
16+
17+
#### **class machine.WDT**(timeout=5)
18+
19+
- **timeout**:设置看门狗超时时间,单位:秒(s);
20+
21+
用于创建一个 WDT 对象并且启动 WDT 功能。一旦启动,设置的超时时间无法改动,WDT 功能无法停止。
22+
23+
如果该函数入参为空,则设置超时时间为 5 秒;如果入参非空,则使用该入参设置 WDT 超时时间,超时时间最小设置为 1 秒。
24+
25+
### 方法
26+
27+
#### **WDT.feed**()
28+
29+
用于执行“喂狗”操作,清空看门狗设备计数。应用程序应该合理的周期性调用该函数,以防止系统重启。
30+
31+
### 示例
32+
33+
``` python
34+
>>> from machine import WDT # 从 machine 导入 WDT 类
35+
>>> wdt = WDT() # 创建 WDT 对象,默认超时时间为 5 秒
36+
>>> wdt = WDT(10) # 创建 WDT 对象,设置超时时间为 10 秒
37+
>>> wdt.feed() # 在 10 秒超时时间内需要执行“喂狗”操作,清空看门狗设备计数,否则系统将重启
38+
```
39+
40+
更多内容可参考 [machine.WDT](http://docs.micropython.org/en/latest/library/machine.WDT.html)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
## machine.Timer
2+
3+
**machine.Timer** 类是 machine 模块下的一个硬件类,用于 Timer 设备的配置和控制,提供对 Timer 设备的操作方法。
4+
5+
- Timer(硬件定时器),是一种用于处理周期性和定时性事件的设备。
6+
- Timer 硬件定时器主要通过内部计数器模块对脉冲信号进行计数,实现周期性设备控制的功能。
7+
- Timer 硬件定时器可以自定义**超时时间****超时回调函数**,并且提供两种**定时器模式**
8+
- `ONE_SHOT`:定时器只执行一次设置的回调函数;
9+
- `PERIOD`:定时器会周期性执行设置的回调函数;
10+
- 打印 Timer 对象会打印出配置的信息。
11+
12+
### 构造函数
13+
14+
在 RT-Thread MicroPython 中 `Timer` 对象的构造函数如下:
15+
16+
#### **class machine.Timer**(id)
17+
18+
- **id**:使用的 Timer 设备编号,`id = 1` 表示编号为 1 的 Timer 设备;
19+
20+
该函数主要用于通过设备编号创建 Timer 设备对象。
21+
22+
### 方法
23+
24+
#### **Timer.init**(mode = Timer.PERIODIC, period = 0, callback = None)
25+
26+
- **mode**:设置 Timer 定时器模式,可以设置两种模式:`ONE_SHOT`(执行一次)、`PERIOD`(周期性执行),默认设置的模式为 `PERIOD` 模式;
27+
28+
- **period**:设置 Timer 定时器定时周期,单位:毫秒(ms)
29+
30+
- **callback**:设置 Timer 定义器超时回调函数,默认设置的函数为 None 空函数,设置的函数格式如下所示:
31+
32+
```python
33+
def callback_test(device): # 回调函数有且只有一个入参,为创建的 Timer 对象
34+
print("Timer callback test")
35+
print(device) # 打印 Timer 对象配置信息
36+
```
37+
38+
该函数使用方式如下示例所示:
39+
40+
```python
41+
timer.init(wdt.PERIOD,5000,callback_test) # 设置定时器模式为周期性执行,超时时间为 5 秒, 超时函数为 callback_test
42+
```
43+
#### **Timer.deinit**()
44+
45+
该函数用于停止并关闭 Timer 设备。
46+
47+
### 常量
48+
49+
下面的常量用来配置 `Timer` 对象。
50+
51+
#### 选择定时器模式:
52+
##### **Timer.PERIODIC**
53+
##### **Timer.ONE_SHOT**
54+
55+
### 示例
56+
57+
```python
58+
>>> from machine import Timer # 从 machine 导入 Timer 类
59+
>>> timer = Timer(11) # 创建 Timer 对象,当前设备编号为 11
60+
>>> # 进入粘贴模式
61+
paste mode; Ctrl-C to cancel, Ctrl-D to finish
62+
=== def callback_test(device): # 定义超时回调函数
63+
=== print("Timer callback test")
64+
>>> timer.init(timer.PERIODIC, 5000, callback_test) # 初始化 Timer 对象,设置定时器模式为循环执行,超时时间为 5 秒,超时回调函数 callback_test
65+
>>> Timer callback test # 5 秒超时循环执行回调函数,打印日志
66+
>>> Timer callback test
67+
>>> Timer callback test
68+
>>> timer.init(timer.ONE_SHOT, 5000, callback_test) # 设置定时器模式为只执行一次,超时时间为 5 秒,超时回调函数为 callback_test
69+
>>> Timer callback test # 5 秒超时后执行一次回调函数,打印日志
70+
>>> timer.deinit() # 停止并关闭 Timer 定时器
71+
```
72+
73+
更多内容可参考 [machine.Timer](http://docs.micropython.org/en/latest/library/machine.Timer.html)

port/genhdr/qstrdefs.generated.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,4 +755,10 @@ QDEF(MP_QSTR_GRAY240, (const byte*)"\x3e\x07" "GRAY240")
755755
QDEF(MP_QSTR_line, (const byte*)"\xcb\x04" "line")
756756
QDEF(MP_QSTR_rectangle, (const byte*)"\xa4\x09" "rectangle")
757757
QDEF(MP_QSTR_circle, (const byte*)"\xb7\x06" "circle")
758+
QDEF(MP_QSTR_WDT, (const byte*)"\x62\x03" "WDT")
759+
QDEF(MP_QSTR_feed, (const byte*)"\xa7\x04" "feed")
760+
QDEF(MP_QSTR_Timer, (const byte*)"\xa2\x05" "Timer")
761+
QDEF(MP_QSTR_ONE_SHOT, (const byte*)"\x5e\x08" "ONE_SHOT")
762+
QDEF(MP_QSTR_PERIODIC, (const byte*)"\x0a\x08" "PERIODIC")
763+
QDEF(MP_QSTR_period, (const byte*)"\xa0\x06" "period")
758764
// This file was automatically generated by makeqstrdata.py

port/machine_timer.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2019 ChenYong ([email protected])
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdint.h>
28+
#include <stdio.h>
29+
#include <string.h>
30+
31+
#include "py/obj.h"
32+
#include "py/runtime.h"
33+
#include "modmachine.h"
34+
#include "mphalport.h"
35+
36+
#ifdef MICROPYTHON_USING_MACHINE_TIMER
37+
38+
#include <rtthread.h>
39+
#include <drivers/hwtimer.h>
40+
#include "machine_timer.h"
41+
42+
typedef struct _machine_timer_obj_t {
43+
mp_obj_base_t base;
44+
rt_device_t timer_device;
45+
mp_obj_t timeout_cb;
46+
uint8_t timerid;
47+
uint32_t timeout;
48+
rt_bool_t is_repeat;
49+
rt_bool_t is_init;
50+
} machine_timer_obj_t;
51+
52+
const mp_obj_type_t machine_timer_type;
53+
54+
STATIC void error_check(bool status, const char *msg) {
55+
if (!status) {
56+
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, msg));
57+
}
58+
}
59+
60+
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
61+
machine_timer_obj_t *self = self_in;
62+
63+
mp_printf(print, "Timer(%p; ", self);
64+
65+
mp_printf(print, "timerid=%d, ", self->timerid);
66+
mp_printf(print, "period=%d, ", self->timeout);
67+
mp_printf(print, "auto_reload=%d)", self->is_repeat);
68+
}
69+
70+
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
71+
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
72+
char timer_dev_name[RT_NAME_MAX] = {0};
73+
int device_id = 0;
74+
75+
// check arguments
76+
mp_arg_check_num(n_args, n_kw, 1, 1, true);
77+
device_id = mp_obj_get_int(args[0]);
78+
79+
// find timer device
80+
rt_snprintf(timer_dev_name, sizeof(timer_dev_name), "timer%d", device_id);
81+
self->timer_device = rt_device_find(timer_dev_name);
82+
if (self->timer_device == RT_NULL || self->timer_device->type != RT_Device_Class_Timer) {
83+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%s) don't exist", timer_dev_name));
84+
}
85+
86+
// initialize timer device
87+
self->base.type = &machine_timer_type;
88+
self->timerid = device_id;
89+
self->timeout = 0;
90+
self->is_repeat = RT_TRUE;
91+
self->is_init = RT_FALSE;
92+
93+
// return constant object
94+
return MP_OBJ_FROM_PTR(self);
95+
}
96+
97+
STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
98+
machine_timer_obj_t *self = self_in;
99+
rt_err_t result = RT_EOK;
100+
101+
if (self->is_init == RT_TRUE) {
102+
result = rt_device_close(self->timer_device);
103+
error_check(result == RT_EOK, "Timer device close error");
104+
self->is_init = RT_FALSE;
105+
}
106+
107+
return mp_const_none;
108+
}
109+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
110+
111+
static machine_timer_obj_t *timer_self = RT_NULL;
112+
113+
STATIC rt_err_t timer_event_handler(rt_device_t dev, rt_size_t size) {
114+
machine_timer_obj_t *self = timer_self;
115+
116+
mp_sched_schedule(self->timeout_cb, MP_OBJ_FROM_PTR(self));
117+
return RT_EOK;
118+
}
119+
120+
STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
121+
machine_timer_obj_t *self = (machine_timer_obj_t *)args[0];
122+
rt_bool_t result = RT_EOK;
123+
int mode = 0;
124+
125+
enum {
126+
ARG_mode,
127+
ARG_period,
128+
ARG_callback,
129+
};
130+
static const mp_arg_t allowed_args[] = {
131+
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = 1} },
132+
{ MP_QSTR_period, MP_ARG_INT, {.u_int = 0xffffffff} },
133+
{ MP_QSTR_callback, MP_ARG_OBJ, {.u_obj = mp_const_none} },
134+
};
135+
136+
mp_arg_val_t dargs[MP_ARRAY_SIZE(allowed_args)];
137+
mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, dargs);
138+
139+
if (2 == n_args) {
140+
self->timeout = dargs[0].u_int;
141+
} else if (3 == n_args) {
142+
self->is_repeat = dargs[ARG_mode].u_int;
143+
self->timeout = dargs[ARG_period].u_int;
144+
} else if (4 == n_args) {
145+
self->is_repeat = dargs[ARG_mode].u_int;
146+
self->timeout = dargs[ARG_period].u_int;
147+
self->timeout_cb = dargs[ARG_callback].u_obj;
148+
} else {
149+
mp_raise_ValueError("invalid format");
150+
}
151+
152+
error_check(self->timeout > 0, "Set timeout value error");
153+
154+
if (self->is_init == RT_FALSE)
155+
{
156+
// open timer device
157+
result = rt_device_open(self->timer_device, RT_DEVICE_OFLAG_RDWR);
158+
error_check(result == RT_EOK, "Timer device open error");
159+
}
160+
161+
if (self->timeout_cb != RT_NULL) {
162+
// set callback timer
163+
if (timer_self && timer_self != self) {
164+
// TODO add multi-timer device support
165+
error_check(result == RT_EOK, "Only supports one timer device work");
166+
} else {
167+
timer_self = self;
168+
}
169+
result = rt_device_set_rx_indicate(self->timer_device, timer_event_handler);
170+
error_check(result == RT_EOK, "Timer set timout callback error");
171+
}
172+
173+
// set timer mode
174+
mode = self->is_repeat ? HWTIMER_MODE_PERIOD : HWTIMER_MODE_ONESHOT;
175+
result = rt_device_control(self->timer_device, HWTIMER_CTRL_MODE_SET, &mode);
176+
error_check(result == RT_EOK, "Timer set mode error");
177+
178+
if (self->timeout) {
179+
rt_hwtimerval_t timeout_s;
180+
rt_size_t len;
181+
182+
timeout_s.sec = self->timeout / 1000; // second
183+
timeout_s.usec = self->timeout % 1000; // microsecond
184+
185+
len = rt_device_write(self->timer_device, 0, &timeout_s, sizeof(timeout_s));
186+
error_check(len == sizeof(timeout_s), "Timer set timout error");
187+
}
188+
189+
self->is_init = RT_TRUE;
190+
191+
return mp_const_none;
192+
}
193+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
194+
195+
STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
196+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
197+
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
198+
{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(RT_FALSE) },
199+
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(RT_TRUE) },
200+
};
201+
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
202+
203+
const mp_obj_type_t machine_timer_type = {
204+
{ &mp_type_type },
205+
.name = MP_QSTR_Timer,
206+
.print = machine_timer_print,
207+
.make_new = machine_timer_make_new,
208+
.locals_dict = (mp_obj_t) &machine_timer_locals_dict,
209+
};
210+
211+
#endif // MICROPYTHON_USING_MACHINE_TIMER
212+

port/machine_timer.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2019 ChenYong ([email protected])
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_MACHINE_TIMER_H
28+
#define MICROPY_INCLUDED_MACHINE_TIMER_H
29+
30+
#include "py/obj.h"
31+
#include <rtthread.h>
32+
33+
extern const mp_obj_type_t machine_timer_type;
34+
35+
#endif // MICROPY_INCLUDED_MACHINE_TIMER_H
36+

0 commit comments

Comments
 (0)