26
26
*/
27
27
28
28
#include "py/runtime.h"
29
- #include "py/mperrno.h"
30
29
#include "py/mphal.h"
31
- #include "fsl_pit.h"
32
- #include "modmachine.h"
33
- #include CLOCK_CONFIG_H
34
-
35
- #define TIMER_MODE_ONE_SHOT (0)
36
- #define TIMER_MODE_PERIODIC (1)
37
- #define TIMER_MIN_PERIOD 1
38
-
39
- #define alarm_callback PIT_IRQHandler
40
- #define PIT_IRQ_ID PIT_IRQn
41
-
42
- typedef struct _machine_timer_obj_t {
43
- mp_obj_base_t base ;
44
- int8_t id ;
45
- int8_t channel ;
46
- uint32_t mode ;
47
- uint32_t tick_hz ;
48
- uint32_t delta_us ; // for periodic mode
49
- mp_obj_t callback ;
50
- } machine_timer_obj_t ;
51
-
52
- static const int8_t channel_no [MICROPY_HW_PIT_NUM_CHANNELS ] = {0 , 2 , 3 }; // no channel 1
53
- static pit_config_t pit_config ;
54
-
55
- // This is the interrupt handler
56
- // To tell which channel fired one has to poll the flags
57
- void alarm_callback (void ) {
58
- for (uint8_t index = 0 ; index < MICROPY_HW_PIT_NUM_CHANNELS ; index ++ ) {
59
- uint32_t flag ;
60
- machine_timer_obj_t * self = MP_STATE_PORT (timer_table )[index ];
61
- if (self != NULL ) {
62
- flag = PIT_GetStatusFlags (PIT , self -> channel );
63
- if (flag & kPIT_TimerFlag ) { // channel fired
64
- PIT_ClearStatusFlags (PIT , self -> channel , kPIT_TimerFlag );
65
- __DSB ();
66
-
67
- mp_sched_schedule (self -> callback , MP_OBJ_FROM_PTR (self ));
68
-
69
- if (self -> mode == TIMER_MODE_ONE_SHOT ) {
70
- PIT_StopTimer (PIT , self -> channel );
71
- }
72
- }
73
- }
74
- }
75
- }
30
+ #include "shared/runtime/softtimer.h"
31
+
32
+ typedef soft_timer_entry_t machine_timer_obj_t ;
33
+
34
+ const mp_obj_type_t machine_timer_type ;
76
35
77
36
STATIC void machine_timer_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
78
37
machine_timer_obj_t * self = MP_OBJ_TO_PTR (self_in );
79
- qstr mode = self -> mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC ;
80
- mp_printf (print , "Timer(channel=%d, mode=%q, period=%d, tick_hz=%d)" ,
81
- self -> id , mode , self -> delta_us / self -> tick_hz , self -> tick_hz );
38
+ qstr mode = self -> mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC ;
39
+ mp_printf (print , "Timer(mode=%q, period=%u)" , mode , self -> delta_ms );
82
40
}
83
41
84
42
STATIC mp_obj_t machine_timer_init_helper (machine_timer_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
85
43
enum { ARG_mode , ARG_callback , ARG_period , ARG_tick_hz , ARG_freq , };
86
44
static const mp_arg_t allowed_args [] = {
87
- { MP_QSTR_mode , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = TIMER_MODE_PERIODIC } },
88
- { MP_QSTR_callback , MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
45
+ { MP_QSTR_mode , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = SOFT_TIMER_MODE_PERIODIC } },
46
+ { MP_QSTR_callback , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
89
47
{ MP_QSTR_period , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0xffffffff } },
90
48
{ MP_QSTR_tick_hz , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 1000 } },
91
49
{ MP_QSTR_freq , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
@@ -96,67 +54,56 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_ar
96
54
mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
97
55
98
56
self -> mode = args [ARG_mode ].u_int ;
57
+
58
+ uint64_t delta_ms = self -> delta_ms ;
99
59
if (args [ARG_freq ].u_obj != mp_const_none ) {
100
60
// Frequency specified in Hz
101
61
#if MICROPY_PY_BUILTINS_FLOAT
102
- self -> delta_us = (uint32_t )(MICROPY_FLOAT_CONST (1000000 .0 ) / mp_obj_get_float (args [ARG_freq ].u_obj ));
62
+ delta_ms = (uint32_t )(MICROPY_FLOAT_CONST (1000 .0 ) / mp_obj_get_float (args [ARG_freq ].u_obj ));
103
63
#else
104
- self -> delta_us = 1000000 / mp_obj_get_int (args [ARG_freq ].u_obj );
64
+ delta_ms = 1000 / mp_obj_get_int (args [ARG_freq ].u_obj );
105
65
#endif
106
- } else {
66
+ } else if ( args [ ARG_period ]. u_int != 0xffffffff ) {
107
67
// Period specified
108
- self -> tick_hz = args [ARG_tick_hz ].u_int ;
109
- self -> delta_us = (uint64_t )args [ARG_period ].u_int * 1000000 / self -> tick_hz ;
110
- }
111
- if (self -> delta_us < TIMER_MIN_PERIOD ) {
112
- self -> delta_us = TIMER_MIN_PERIOD ;
68
+ delta_ms = (uint64_t )args [ARG_period ].u_int * 1000 / args [ARG_tick_hz ].u_int ;
113
69
}
114
70
115
- self -> callback = args [ARG_callback ].u_obj ;
116
-
117
- // Set timer period for channel id
118
- PIT_SetTimerPeriod (PIT , self -> channel , USEC_TO_COUNT (self -> delta_us , BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT ));
119
-
120
- // Enable timer interrupts for the channel
121
- PIT_EnableInterrupts (PIT , self -> channel , kPIT_TimerInterruptEnable );
71
+ if (delta_ms < 1 ) {
72
+ delta_ms = 1 ;
73
+ } else if (delta_ms >= 0x40000000 ) {
74
+ mp_raise_ValueError (MP_ERROR_TEXT ("period too large" ));
75
+ }
76
+ self -> delta_ms = (uint32_t )delta_ms ;
122
77
123
- // Enable at the NVIC
124
- EnableIRQ (PIT_IRQ_ID );
78
+ if (args [ARG_callback ].u_obj != MP_OBJ_NULL ) {
79
+ self -> py_callback = args [ARG_callback ].u_obj ;
80
+ }
125
81
126
- // Start channel 0
127
- PIT_StartTimer (PIT , self -> channel );
82
+ if (self -> py_callback != mp_const_none ) {
83
+ soft_timer_insert (self , self -> delta_ms );
84
+ }
128
85
129
86
return mp_const_none ;
130
87
}
131
88
132
89
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 ) {
133
- machine_timer_obj_t * self ;
134
-
135
- // Get timer id in the range of 0..2
136
- mp_int_t id = 0 ;
90
+ machine_timer_obj_t * self = m_new_obj (machine_timer_obj_t );
91
+ self -> pairheap .base .type = & machine_timer_type ;
92
+ self -> flags = SOFT_TIMER_FLAG_PY_CALLBACK | SOFT_TIMER_FLAG_GC_ALLOCATED ;
93
+ self -> delta_ms = 1000 ;
94
+ self -> py_callback = mp_const_none ;
95
+
96
+ // Get timer id (only soft timer (-1) supported at the moment)
97
+ mp_int_t id = -1 ;
137
98
if (n_args > 0 ) {
138
99
id = mp_obj_get_int (args [0 ]);
139
100
-- n_args ;
140
101
++ args ;
141
102
}
142
- if (id < 0 || id >= MICROPY_HW_PIT_NUM_CHANNELS ) {
143
- mp_raise_ValueError (MP_ERROR_TEXT ("Timer does not exist" ));
103
+ if (id != -1 ) {
104
+ mp_raise_ValueError (MP_ERROR_TEXT ("Timer doesn't exist" ));
144
105
}
145
106
146
- // check, if a timer exists at that channel and stop it first
147
- if (MP_STATE_PORT (timer_table )[id ] != NULL ) {
148
- PIT_StopTimer (PIT , channel_no [id ]);
149
- self = MP_STATE_PORT (timer_table )[id ];
150
- } else {
151
- self = m_new_obj_with_finaliser (machine_timer_obj_t );
152
- self -> base .type = & machine_timer_type ;
153
- MP_STATE_PORT (timer_table )[id ] = self ;
154
- }
155
-
156
- // Set initial values
157
- self -> id = id ;
158
- self -> channel = channel_no [id ];
159
-
160
107
if (n_args > 0 || n_kw > 0 ) {
161
108
// Start the timer
162
109
mp_map_t kw_args ;
@@ -167,47 +114,26 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
167
114
return MP_OBJ_FROM_PTR (self );
168
115
}
169
116
170
- STATIC mp_obj_t machine_timer___del__ (mp_obj_t self_in ) {
171
- machine_timer_obj_t * self = MP_OBJ_TO_PTR (self_in );
172
- PIT_StopTimer (PIT , self -> channel );
173
- MP_STATE_PORT (timer_table )[self -> id ] = NULL ;
174
- return mp_const_none ;
175
- }
176
- STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer___del___obj , machine_timer___del__ );
177
-
178
117
STATIC mp_obj_t machine_timer_init (size_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
179
118
machine_timer_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
180
- PIT_StopTimer ( PIT , self -> channel );
119
+ soft_timer_remove ( self );
181
120
return machine_timer_init_helper (self , n_args - 1 , args + 1 , kw_args );
182
121
}
183
122
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_timer_init_obj , 1 , machine_timer_init );
184
123
185
124
STATIC mp_obj_t machine_timer_deinit (mp_obj_t self_in ) {
186
125
machine_timer_obj_t * self = MP_OBJ_TO_PTR (self_in );
187
- PIT_StopTimer ( PIT , self -> channel );
126
+ soft_timer_remove ( self );
188
127
return mp_const_none ;
189
128
}
190
129
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_timer_deinit_obj , machine_timer_deinit );
191
130
192
- // Initialize clock an first config
193
- void machine_timer_init_PIT (void ) {
194
- // PIT timer
195
- // Enable clock gate for GPIO1
196
- CLOCK_EnableClock (kCLOCK_Gpio1 ); // ?
197
- // Set PERCLK_CLK divider to 1
198
- CLOCK_SetDiv (kCLOCK_PerclkDiv , 0U );
199
-
200
- PIT_GetDefaultConfig (& pit_config );
201
- PIT_Init (PIT , & pit_config );
202
- }
203
-
204
131
STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table [] = {
205
- { MP_ROM_QSTR (MP_QSTR___del__ ), MP_ROM_PTR (& machine_timer___del___obj ) },
206
132
{ MP_ROM_QSTR (MP_QSTR_init ), MP_ROM_PTR (& machine_timer_init_obj ) },
207
133
{ MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& machine_timer_deinit_obj ) },
208
134
209
- { MP_ROM_QSTR (MP_QSTR_ONE_SHOT ), MP_ROM_INT (TIMER_MODE_ONE_SHOT ) },
210
- { MP_ROM_QSTR (MP_QSTR_PERIODIC ), MP_ROM_INT (TIMER_MODE_PERIODIC ) },
135
+ { MP_ROM_QSTR (MP_QSTR_ONE_SHOT ), MP_ROM_INT (SOFT_TIMER_MODE_ONE_SHOT ) },
136
+ { MP_ROM_QSTR (MP_QSTR_PERIODIC ), MP_ROM_INT (SOFT_TIMER_MODE_PERIODIC ) },
211
137
};
212
138
STATIC MP_DEFINE_CONST_DICT (machine_timer_locals_dict , machine_timer_locals_dict_table );
213
139
@@ -219,5 +145,3 @@ MP_DEFINE_CONST_OBJ_TYPE(
219
145
print , machine_timer_print ,
220
146
locals_dict , & machine_timer_locals_dict
221
147
);
222
-
223
- MP_REGISTER_ROOT_POINTER (struct _machine_timer_obj_t * timer_table [MICROPY_HW_PIT_NUM_CHANNELS ]);
0 commit comments