1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <vfsdev/timer_dev.h>
9
10 #include "aos_hal_timer.h"
11 #include "py/builtin.h"
12 #include "py/gc.h"
13 #include "py/mperrno.h"
14 #include "py/obj.h"
15 #include "py/runtime.h"
16 #include "py/stackctrl.h"
17 #include "ulog/ulog.h"
18 #include "utility.h"
19
20 #define LOG_TAG "machine_timer"
21
22 #define TIMER_MODE_ONESHOT (TIMER_RELOAD_MANU)
23 #define TIMER_MODE_PERIODIC (TIMER_RELOAD_AUTO)
24 #define TIMER_DEFAULT_PERIOD (1000000U)
25 typedef struct _machine_timer_obj_t {
26 mp_obj_base_t base;
27 mp_uint_t port;
28 timer_dev_t dev;
29 mp_obj_t callback;
30 } machine_timer_obj_t;
31
32 const mp_obj_type_t machine_timer_type;
33
machine_timer_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)34 STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
35 {
36 machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
37 mp_printf(print, "port=%d, ", self->port);
38 mp_printf(print, "period=%d, ", self->dev.config.period);
39 mp_printf(print, "reload_mode=%d, ", self->dev.config.reload_mode);
40 }
41
machine_timer_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)42 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)
43 {
44 mp_arg_check_num(n_args, n_kw, 1, 1, false);
45 mp_uint_t port = mp_obj_get_int(args[0]);
46
47 machine_timer_obj_t *timer_obj = m_new_obj(machine_timer_obj_t);
48 if (!timer_obj) {
49 mp_raise_OSError(MP_EINVAL);
50 return mp_const_none;
51 }
52 memset(timer_obj, 0, sizeof(machine_timer_obj_t));
53
54 timer_obj->base.type = &machine_timer_type;
55 timer_obj->port = port;
56 timer_obj->dev.port = port;
57
58 return MP_OBJ_FROM_PTR(timer_obj);
59 }
60
machine_timer_disable(timer_dev_t * tim)61 STATIC void machine_timer_disable(timer_dev_t *tim)
62 {
63 aos_hal_timer_stop(tim);
64 }
65
aos_hal_timer_reload(timer_dev_t * tim)66 STATIC mp_int_t aos_hal_timer_reload(timer_dev_t *tim)
67 {
68 int32_t *p_fd = (int32_t *)tim->priv;
69 return ioctl(*p_fd, IOC_TIMER_RELOAD, (unsigned long)false);
70 }
71
machine_timer_isr(void * self_in)72 STATIC void machine_timer_isr(void *self_in)
73 {
74 machine_timer_obj_t *self = (machine_timer_obj_t *)self_in;
75 mp_obj_t callback = self->callback;
76 if (callback != mp_const_none && mp_obj_is_callable(callback)) {
77 callback_to_python(callback, self);
78 }
79 }
80
machine_timer_enable(machine_timer_obj_t * self)81 STATIC void machine_timer_enable(machine_timer_obj_t *self)
82 {
83 timer_dev_t *tim = &self->dev;
84
85 if (tim != NULL) {
86 aos_hal_timer_init(tim);
87 aos_hal_timer_start(tim);
88 }
89 }
90
machine_timer_init_helper(machine_timer_obj_t * self,mp_uint_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)91 STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args,
92 mp_map_t *kw_args)
93 {
94 enum {
95 ARG_period,
96 ARG_mode,
97 ARG_callback,
98 };
99
100 static const mp_arg_t allowed_args[] = {
101 { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = TIMER_DEFAULT_PERIOD } },
102 { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = TIMER_MODE_PERIODIC } },
103 { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } },
104 };
105
106 machine_timer_disable(&self->dev);
107
108 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
109 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
110
111 if (self == NULL) {
112 LOGE(LOG_TAG, "%s: hal_timer_init failed\n", __func__);
113 return mp_const_none;
114 }
115
116 self->callback = args[ARG_callback].u_obj;
117
118 self->dev.port = self->port;
119 self->dev.config.reload_mode = args[ARG_mode].u_int;
120 self->dev.config.period = (mp_uint_t)args[ARG_period].u_int * 1000UL;
121 self->dev.config.arg = self;
122 self->dev.config.cb = machine_timer_isr;
123
124 machine_timer_enable(self);
125 return mp_const_none;
126 }
127
machine_timer_deinit(mp_obj_t self_in)128 STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in)
129 {
130 machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
131 timer_dev_t *tim = &self->dev;
132 aos_hal_timer_stop(tim);
133 return mp_const_none;
134 }
135 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
136
machine_timer_init(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)137 STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args)
138 {
139 return machine_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
140 }
141 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
142
machine_timer_period(mp_obj_t self_in,mp_obj_t period)143 STATIC mp_obj_t machine_timer_period(mp_obj_t self_in, mp_obj_t period)
144 {
145 machine_timer_obj_t *self = self_in;
146 if (self_in == NULL) {
147 mp_raise_OSError(MP_EINVAL);
148 return mp_const_none;
149 } else {
150 self->dev.config.period = mp_obj_get_int(period);
151 }
152 timer_config_t para = self->dev.config;
153
154 timer_dev_t *tim = &self->dev;
155 mp_int_t ret = aos_hal_timer_para_chg(tim, para);
156 return MP_OBJ_NEW_SMALL_INT(ret);
157 }
158 STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_timer_period_obj, machine_timer_period);
159
machine_timer_start(mp_obj_t self_in)160 STATIC mp_obj_t machine_timer_start(mp_obj_t self_in)
161 {
162 machine_timer_obj_t *self = self_in;
163 timer_dev_t *tim = &self->dev;
164 mp_int_t ret = aos_hal_timer_start(tim);
165 return MP_OBJ_NEW_SMALL_INT(ret);
166 }
167 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_start_obj, machine_timer_start);
168
machine_timer_stop(mp_obj_t self_in)169 STATIC mp_obj_t machine_timer_stop(mp_obj_t self_in)
170 {
171 machine_timer_obj_t *self = self_in;
172 timer_dev_t *tim = &self->dev;
173 aos_hal_timer_stop(tim);
174 return mp_const_none;
175 }
176 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop);
177
machine_timer_reload(mp_obj_t self_in)178 STATIC mp_obj_t machine_timer_reload(mp_obj_t self_in)
179 {
180 machine_timer_obj_t *self = self_in;
181 timer_dev_t *tim = &self->dev;
182 mp_int_t ret = aos_hal_timer_reload(tim);
183 return MP_OBJ_NEW_SMALL_INT(ret);
184 }
185 STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_reload_obj, machine_timer_reload);
186
187 STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
188 { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) },
189 { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
190 { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
191 { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_start_obj) },
192 { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj) },
193 { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&machine_timer_period_obj) },
194 { MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&machine_timer_reload_obj) },
195
196 { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONESHOT) },
197 { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC) },
198 };
199 STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
200
201 const mp_obj_type_t machine_timer_type = {
202 { &mp_type_type },
203 .name = MP_QSTR_Timer,
204 .print = machine_timer_print,
205 .make_new = machine_timer_make_new,
206 .locals_dict = (mp_obj_t)&machine_timer_locals_dict,
207 };
208