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