Skip to content

Commit 4a1edc4

Browse files
iabdalkaderdpgeorge
authored andcommitted
alif/machine_pin: Add support for machine.Pin IRQ.
Matches existing `Pin.irq()` API. Both rising and falling edge work. Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
1 parent 1b0cdc0 commit 4a1edc4

File tree

4 files changed

+203
-0
lines changed

4 files changed

+203
-0
lines changed

ports/alif/irq.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#define IRQ_PRI_USB NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 7, 0)
4949
#define IRQ_PRI_HWSEM NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 8, 0)
5050
#define IRQ_PRI_GPU NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 10, 0)
51+
#define IRQ_PRI_GPIO NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 50, 0)
5152
#define IRQ_PRI_RTC NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 100, 0)
5253
#define IRQ_PRI_CYW43 NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 126, 0)
5354
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 127, 0)

ports/alif/machine_pin.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,76 @@
3030
#include "extmod/virtpin.h"
3131
#include "shared/runtime/mpirq.h"
3232

33+
#ifndef MACHINE_PIN_NUM_VECTORS
34+
#define MACHINE_PIN_NUM_PORT_IO (8)
35+
#define MACHINE_PIN_NUM_VECTORS (16 * MACHINE_PIN_NUM_PORT_IO)
36+
#endif
37+
38+
typedef struct _machine_pin_irq_obj_t {
39+
mp_irq_obj_t base;
40+
uint32_t flags;
41+
uint32_t trigger;
42+
IRQn_Type irq_num;
43+
bool reserved; // for use by other drivers
44+
} machine_pin_irq_obj_t;
45+
46+
#define MACHINE_PIN_IRQ_INDEX(port, pin) \
47+
((port) * MACHINE_PIN_NUM_PORT_IO + (pin))
48+
49+
#define MACHINE_PIN_IRQ_OBJECT(port, pin) \
50+
(MP_STATE_PORT(machine_pin_irq_obj[MACHINE_PIN_IRQ_INDEX((port), (pin))]))
51+
52+
// Defines a single GPIO IRQ handler
53+
#define DEFINE_GPIO_IRQ_HANDLER(pname, port, pin) \
54+
void pname##_IRQ##pin##Handler(void) { \
55+
machine_pin_irq_obj_t *irq = MACHINE_PIN_IRQ_OBJECT(port, pin); \
56+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(irq->base.parent); \
57+
gpio_interrupt_eoi(self->gpio, pin); \
58+
irq->flags = irq->trigger; \
59+
mp_irq_handler(&irq->base); \
60+
}
61+
62+
// Defines all 8 pin IRQ handlers for a port
63+
#define DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(gpio, port) \
64+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 0) \
65+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 1) \
66+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 2) \
67+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 3) \
68+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 4) \
69+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 5) \
70+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 6) \
71+
DEFINE_GPIO_IRQ_HANDLER(gpio, port, 7)
72+
73+
// Generate handlers for GPIO ports 0 to 14 + LPGPIO
74+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO0, 0)
75+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO1, 1)
76+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO2, 2)
77+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO3, 3)
78+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO4, 4)
79+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO5, 5)
80+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO6, 6)
81+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO7, 7)
82+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO8, 8)
83+
84+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 0)
85+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 1)
86+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 2)
87+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 3)
88+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 4)
89+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 5)
90+
// DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 6) // Reserved for WiFi
91+
DEFINE_GPIO_IRQ_HANDLER(GPIO9, 9, 7)
92+
93+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO10, 10)
94+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO11, 11)
95+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO12, 12)
96+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO13, 13)
97+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(GPIO14, 14)
98+
DEFINE_GPIO_IRQ_HANDLERS_FOR_PORT(LPGPIO, 15)
99+
33100
extern const mp_obj_dict_t machine_pin_cpu_pins_locals_dict;
34101
extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;
102+
static const mp_irq_methods_t machine_pin_irq_methods;
35103

36104
static const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name) {
37105
const mp_map_t *named_map = &named_pins->map;
@@ -171,6 +239,7 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
171239
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
172240
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
173241
}
242+
174243
return MP_OBJ_FROM_PTR(self);
175244
}
176245

@@ -225,6 +294,129 @@ static mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
225294
}
226295
static MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
227296

297+
static mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t trigger) {
298+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
299+
machine_pin_irq_obj_t *irq = MACHINE_PIN_IRQ_OBJECT(self->port, self->pin);
300+
301+
irq->flags = 0;
302+
irq->trigger = trigger;
303+
304+
// Disable IRQs.
305+
gpio_disable_interrupt(self->gpio, self->pin);
306+
gpio_mask_interrupt(self->gpio, self->pin);
307+
308+
NVIC_ClearPendingIRQ(irq->irq_num);
309+
NVIC_DisableIRQ(irq->irq_num);
310+
311+
// Return if the trigger is disabled.
312+
if (trigger == 0) {
313+
return 0;
314+
}
315+
316+
// Clear and enable GPIO IRQ.
317+
gpio_enable_interrupt(self->gpio, self->pin);
318+
gpio_unmask_interrupt(self->gpio, self->pin);
319+
320+
// Clear GPIO config.
321+
self->gpio->GPIO_INT_BOTHEDGE &= ~(1 << self->pin);
322+
self->gpio->GPIO_INT_POLARITY &= ~(1 << self->pin);
323+
self->gpio->GPIO_INTTYPE_LEVEL &= ~(1 << self->pin);
324+
325+
// Configure GPIO IRQ trigger
326+
if (trigger == MP_HAL_PIN_TRIGGER_FALL) {
327+
gpio_interrupt_set_edge_trigger(self->gpio, self->pin);
328+
gpio_interrupt_set_polarity_low(self->gpio, self->pin);
329+
} else if (trigger == MP_HAL_PIN_TRIGGER_RISE) {
330+
gpio_interrupt_set_edge_trigger(self->gpio, self->pin);
331+
gpio_interrupt_set_polarity_high(self->gpio, self->pin);
332+
} else if (trigger == (MP_HAL_PIN_TRIGGER_FALL | MP_HAL_PIN_TRIGGER_RISE)) {
333+
gpio_interrupt_set_both_edge_trigger(self->gpio, self->pin);
334+
} else {
335+
mp_raise_ValueError(MP_ERROR_TEXT("Invalid IRQ trigger"));
336+
}
337+
338+
// Clear GPIO IRQ (must be done after configuring trigger)
339+
gpio_interrupt_eoi(self->gpio, self->pin);
340+
341+
// Clear and enable NVIC GPIO IRQ.
342+
NVIC_ClearPendingIRQ(irq->irq_num);
343+
NVIC_SetPriority(irq->irq_num, IRQ_PRI_GPIO);
344+
NVIC_EnableIRQ(irq->irq_num);
345+
346+
return 0;
347+
}
348+
349+
static mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) {
350+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
351+
machine_pin_irq_obj_t *irq = MACHINE_PIN_IRQ_OBJECT(self->port, self->pin);
352+
353+
if (info_type == MP_IRQ_INFO_FLAGS) {
354+
return irq->flags;
355+
} else if (info_type == MP_IRQ_INFO_TRIGGERS) {
356+
return irq->trigger;
357+
}
358+
return 0;
359+
}
360+
361+
static const mp_irq_methods_t machine_pin_irq_methods = {
362+
.trigger = machine_pin_irq_trigger,
363+
.info = machine_pin_irq_info,
364+
};
365+
366+
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
367+
static mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
368+
enum { ARG_handler, ARG_trigger, ARG_hard };
369+
static const mp_arg_t allowed_args[] = {
370+
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
371+
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_HAL_PIN_TRIGGER_FALL | MP_HAL_PIN_TRIGGER_RISE} },
372+
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
373+
};
374+
375+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
376+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
377+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
378+
379+
machine_pin_irq_obj_t *irq = MACHINE_PIN_IRQ_OBJECT(self->port, self->pin);
380+
381+
// Allocate a new IRQ object if it doesn't exist.
382+
if (irq == NULL) {
383+
irq = m_new_obj(machine_pin_irq_obj_t);
384+
uint32_t idx = MACHINE_PIN_IRQ_INDEX(self->port, self->pin);
385+
386+
irq->base.base.type = &mp_irq_type;
387+
irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods;
388+
irq->base.parent = MP_OBJ_FROM_PTR(self);
389+
irq->base.handler = mp_const_none;
390+
irq->base.ishard = false;
391+
irq->reserved = false;
392+
irq->irq_num = (self->port < 15) ? (GPIO0_IRQ0_IRQn + idx) : (LPGPIO_IRQ0_IRQn + self->pin);
393+
MP_STATE_PORT(machine_pin_irq_obj[idx]) = irq;
394+
}
395+
396+
if (n_args > 1 || kw_args->used != 0) {
397+
if (irq->reserved) {
398+
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Pin IRQ is reserved"));
399+
}
400+
irq->base.handler = args[ARG_handler].u_obj;
401+
irq->base.ishard = args[ARG_hard].u_bool;
402+
machine_pin_irq_trigger(self, args[ARG_trigger].u_int);
403+
}
404+
405+
return MP_OBJ_FROM_PTR(irq);
406+
}
407+
static MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
408+
409+
void machine_pin_irq_deinit(void) {
410+
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(machine_pin_irq_obj)); i++) {
411+
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[i]);
412+
if (irq != NULL) {
413+
machine_pin_obj_t *self = MP_OBJ_TO_PTR(irq->base.parent);
414+
machine_pin_irq_trigger(self, 0);
415+
MP_STATE_PORT(machine_pin_irq_obj[i]) = NULL;
416+
}
417+
}
418+
}
419+
228420
static MP_DEFINE_CONST_OBJ_TYPE(
229421
pin_cpu_pins_obj_type,
230422
MP_QSTR_cpu,
@@ -248,6 +440,7 @@ static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
248440
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) },
249441
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_high_obj) },
250442
{ MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
443+
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
251444

252445
// class attributes
253446
{ MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) },
@@ -259,6 +452,8 @@ static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
259452
{ MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_OPEN_DRAIN) },
260453
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(MP_HAL_PIN_PULL_UP) },
261454
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(MP_HAL_PIN_PULL_DOWN) },
455+
{ MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_FALL) },
456+
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_RISE) },
262457
};
263458
static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
264459

@@ -296,3 +491,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
296491
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
297492
return machine_pin_find(obj);
298493
}
494+
495+
MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_obj[MACHINE_PIN_NUM_VECTORS]);

ports/alif/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
extern uint8_t __StackTop, __StackLimit;
5757
extern uint8_t __GcHeapStart, __GcHeapEnd;
58+
extern void machine_pin_irq_deinit(void);
5859

5960
MP_NORETURN void panic(const char *msg) {
6061
mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14);
@@ -164,6 +165,7 @@ int main(void) {
164165
mp_bluetooth_deinit();
165166
#endif
166167
soft_timer_deinit();
168+
machine_pin_irq_deinit();
167169
gc_sweep_all();
168170
mp_deinit();
169171
}

ports/alif/mphalport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ extern ringbuf_t stdin_ringbuf;
9090
#define MP_HAL_PIN_SPEED_LOW (0)
9191
#define MP_HAL_PIN_SPEED_HIGH (PADCTRL_SLEW_RATE_FAST)
9292

93+
#define MP_HAL_PIN_TRIGGER_FALL (1)
94+
#define MP_HAL_PIN_TRIGGER_RISE (2)
95+
9396
#define mp_hal_pin_obj_t const machine_pin_obj_t *
9497

9598
#define MP_HAL_PIN_ALT(function, unit) (MP_HAL_PIN_ALT_MAKE((MP_HAL_PIN_ALT_##function), (unit)))

0 commit comments

Comments
 (0)