4
4
* The MIT License (MIT)
5
5
*
6
6
* Copyright (c) 2020 Philipp Ebensberger
7
+ * Copyright (c) 2021 Robert Hammelrath
7
8
*
8
9
* Permission is hereby granted, free of charge, to any person obtaining a copy
9
10
* of this software and associated documentation files (the "Software"), to deal
30
31
31
32
#include "py/runtime.h"
32
33
#include "py/mphal.h"
34
+ #include "lib/utils/mpirq.h"
33
35
#include "pin.h"
34
- #include "mphalport.h"
35
36
36
37
// Local functions
37
38
STATIC mp_obj_t machine_pin_obj_init_helper (const machine_pin_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args );
@@ -68,6 +69,95 @@ const mp_obj_type_t machine_pin_board_pins_obj_type = {
68
69
.locals_dict = (mp_obj_t )& machine_pin_board_pins_locals_dict ,
69
70
};
70
71
72
+ STATIC const mp_irq_methods_t machine_pin_irq_methods ;
73
+
74
+ static GPIO_Type * gpiobases [] = GPIO_BASE_PTRS ;
75
+ STATIC const uint16_t GPIO_combined_low_irqs [] = GPIO_COMBINED_LOW_IRQS ;
76
+ STATIC const uint16_t GPIO_combined_high_irqs [] = GPIO_COMBINED_HIGH_IRQS ;
77
+ STATIC const uint16_t IRQ_mapping [] = {kGPIO_NoIntmode , kGPIO_IntRisingEdge , kGPIO_IntFallingEdge , kGPIO_IntRisingOrFallingEdge };
78
+ #define GET_PIN_IRQ_INDEX (gpio_nr , pin ) ((gpio_nr - 1) * 32 + pin)
79
+
80
+ int GPIO_get_instance (GPIO_Type * gpio ) {
81
+ int gpio_nr ;
82
+ for (gpio_nr = 0 ; gpio_nr < ARRAY_SIZE (gpiobases ); gpio_nr ++ ) {
83
+ if (gpio == gpiobases [gpio_nr ]) {
84
+ return gpio_nr ;
85
+ }
86
+ }
87
+ return 0 ;
88
+ }
89
+
90
+ void call_handler (GPIO_Type * gpio , int gpio_nr , int pin ) {
91
+ uint32_t mask = 1 << pin ;
92
+ uint32_t isr = gpio -> ISR & gpio -> IMR ;
93
+ for (int i = 0 ; i < 16 ; i ++ , pin ++ , mask <<= 1 ) {
94
+ // Did the ISR fire? Consider only the bits that are enabled.
95
+ if (isr & mask ) {
96
+ gpio -> ISR = mask ; // clear the ISR flag
97
+ int index = GET_PIN_IRQ_INDEX (gpio_nr , pin );
98
+ machine_pin_irq_obj_t * irq = MP_STATE_PORT (machine_pin_irq_objects [index ]);
99
+ if (irq != NULL ) {
100
+ irq -> flags = irq -> trigger ;
101
+ mp_irq_handler (& irq -> base );
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ // 10 GPIO IRQ handlers, each covering 16 bits.
108
+
109
+ void GPIO1_Combined_0_15_IRQHandler (void ) {
110
+ call_handler (gpiobases [1 ], 1 , 0 );
111
+ }
112
+
113
+ void GPIO1_Combined_16_31_IRQHandler (void ) {
114
+ call_handler (gpiobases [1 ], 1 , 16 );
115
+ }
116
+
117
+ void GPIO2_Combined_0_15_IRQHandler (void ) {
118
+ call_handler (gpiobases [2 ], 2 , 0 );
119
+ }
120
+
121
+ void GPIO2_Combined_16_31_IRQHandler (void ) {
122
+ call_handler (gpiobases [2 ], 2 , 16 );
123
+ }
124
+
125
+ void GPIO3_Combined_0_15_IRQHandler (void ) {
126
+ call_handler (gpiobases [3 ], 3 , 0 );
127
+ }
128
+
129
+ void GPIO3_Combined_16_31_IRQHandler (void ) {
130
+ call_handler (gpiobases [3 ], 3 , 16 );
131
+ }
132
+
133
+ void GPIO4_Combined_0_15_IRQHandler (void ) {
134
+ call_handler (gpiobases [4 ], 4 , 0 );
135
+ }
136
+
137
+ void GPIO4_Combined_16_31_IRQHandler (void ) {
138
+ call_handler (gpiobases [4 ], 4 , 16 );
139
+ }
140
+
141
+ void GPIO5_Combined_0_15_IRQHandler (void ) {
142
+ call_handler (gpiobases [5 ], 5 , 0 );
143
+ }
144
+
145
+ void GPIO5_Combined_16_31_IRQHandler (void ) {
146
+ call_handler (gpiobases [5 ], 5 , 16 );
147
+ }
148
+
149
+ // Deinit all pin IRQ handlers.
150
+ void machine_pin_irq_deinit (void ) {
151
+ for (int i = 0 ; i < ARRAY_SIZE (MP_STATE_PORT (machine_pin_irq_objects )); ++ i ) {
152
+ machine_pin_irq_obj_t * irq = MP_STATE_PORT (machine_pin_irq_objects [i ]);
153
+ if (irq != NULL ) {
154
+ machine_pin_obj_t * self = MP_OBJ_TO_PTR (irq -> base .parent );
155
+ GPIO_PortDisableInterrupts (self -> gpio , 1U << self -> pin );
156
+ MP_STATE_PORT (machine_pin_irq_objects [i ]) = NULL ;
157
+ }
158
+ }
159
+ }
160
+
71
161
// Simplified mode setting used by the extmod modules
72
162
void machine_pin_set_mode (const machine_pin_obj_t * self , uint8_t mode ) {
73
163
gpio_pin_config_t pin_config = {kGPIO_DigitalInput , 1 , kGPIO_NoIntmode };
@@ -234,6 +324,69 @@ STATIC mp_obj_t machine_pin_init(size_t n_args, const mp_obj_t *args, mp_map_t *
234
324
}
235
325
MP_DEFINE_CONST_FUN_OBJ_KW (machine_pin_init_obj , 1 , machine_pin_init );
236
326
327
+ // pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
328
+ STATIC mp_obj_t machine_pin_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
329
+ enum { ARG_handler , ARG_trigger , ARG_hard };
330
+ static const mp_arg_t allowed_args [] = {
331
+ { MP_QSTR_handler , MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
332
+ { MP_QSTR_trigger , MP_ARG_INT , {.u_int = 3 } },
333
+ { MP_QSTR_hard , MP_ARG_BOOL , {.u_bool = false} },
334
+ };
335
+ machine_pin_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
336
+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
337
+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
338
+
339
+ // Get the IRQ object.
340
+ uint32_t gpio_nr = GPIO_get_instance (self -> gpio );
341
+ uint32_t index = GET_PIN_IRQ_INDEX (gpio_nr , self -> pin );
342
+ if (index >= ARRAY_SIZE (MP_STATE_PORT (machine_pin_irq_objects ))) {
343
+ mp_raise_ValueError (MP_ERROR_TEXT ("IRQ not supported on given Pin" ));
344
+ }
345
+ machine_pin_irq_obj_t * irq = MP_STATE_PORT (machine_pin_irq_objects [index ]);
346
+
347
+ // Allocate the IRQ object if it doesn't already exist.
348
+ if (irq == NULL ) {
349
+ irq = m_new_obj (machine_pin_irq_obj_t );
350
+ irq -> base .base .type = & mp_irq_type ;
351
+ irq -> base .methods = (mp_irq_methods_t * )& machine_pin_irq_methods ;
352
+ irq -> base .parent = MP_OBJ_FROM_PTR (self );
353
+ irq -> base .handler = mp_const_none ;
354
+ irq -> base .ishard = false;
355
+ MP_STATE_PORT (machine_pin_irq_objects [index ]) = irq ;
356
+ }
357
+
358
+ if (n_args > 1 || kw_args -> used != 0 ) {
359
+ // Configure IRQ.
360
+ uint32_t irq_num = self -> pin < 16 ? GPIO_combined_low_irqs [gpio_nr ] : GPIO_combined_high_irqs [gpio_nr ];
361
+
362
+ // Disable all IRQs from the affected source while data is updated.
363
+ DisableIRQ (irq_num );
364
+ GPIO_PortDisableInterrupts (self -> gpio , 1U << self -> pin );
365
+
366
+ // Update IRQ data.
367
+ irq -> base .handler = args [ARG_handler ].u_obj ;
368
+ irq -> base .ishard = args [ARG_hard ].u_bool ;
369
+ irq -> flags = 0 ;
370
+ if (args [ARG_trigger ].u_int >= ARRAY_SIZE (IRQ_mapping )) {
371
+ mp_raise_ValueError (MP_ERROR_TEXT ("IRQ mode not supported" ));
372
+ }
373
+ irq -> trigger = IRQ_mapping [args [ARG_trigger ].u_int ];
374
+
375
+ // Enable IRQ if a handler is given.
376
+ if (args [ARG_handler ].u_obj != mp_const_none ) {
377
+ // Set the pin mode
378
+ GPIO_PinSetInterruptConfig (self -> gpio , self -> pin , irq -> trigger );
379
+ // Enable the specific Pin interrupt
380
+ GPIO_PortEnableInterrupts (self -> gpio , 1U << self -> pin );
381
+ }
382
+ // Enable LEVEL1 interrupt again
383
+ EnableIRQ (irq_num );
384
+ }
385
+
386
+ return MP_OBJ_FROM_PTR (irq );
387
+ }
388
+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_pin_irq_obj , 1 , machine_pin_irq );
389
+
237
390
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table [] = {
238
391
// instance methods
239
392
{ MP_ROM_QSTR (MP_QSTR_off ), MP_ROM_PTR (& machine_pin_off_obj ) },
@@ -242,6 +395,7 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
242
395
{ MP_ROM_QSTR (MP_QSTR_high ), MP_ROM_PTR (& machine_pin_on_obj ) },
243
396
{ MP_ROM_QSTR (MP_QSTR_value ), MP_ROM_PTR (& machine_pin_value_obj ) },
244
397
{ MP_ROM_QSTR (MP_QSTR_init ), MP_ROM_PTR (& machine_pin_init_obj ) },
398
+ { MP_ROM_QSTR (MP_QSTR_irq ), MP_ROM_PTR (& machine_pin_irq_obj ) },
245
399
// class attributes
246
400
{ MP_ROM_QSTR (MP_QSTR_board ), MP_ROM_PTR (& machine_pin_board_pins_obj_type ) },
247
401
{ MP_ROM_QSTR (MP_QSTR_cpu ), MP_ROM_PTR (& machine_pin_cpu_pins_obj_type ) },
@@ -265,6 +419,9 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
265
419
{ MP_ROM_QSTR (MP_QSTR_POWER_5 ), MP_ROM_INT (PIN_DRIVE_POWER_5 ) }, // R0/6
266
420
{ MP_ROM_QSTR (MP_QSTR_POWER_6 ), MP_ROM_INT (PIN_DRIVE_POWER_6 ) }, // R0/7
267
421
422
+ { MP_ROM_QSTR (MP_QSTR_IRQ_RISING ), MP_ROM_INT (1 ) },
423
+ { MP_ROM_QSTR (MP_QSTR_IRQ_FALLING ), MP_ROM_INT (2 ) },
424
+
268
425
};
269
426
STATIC MP_DEFINE_CONST_DICT (machine_pin_locals_dict , machine_pin_locals_dict_table );
270
427
@@ -285,3 +442,37 @@ const mp_obj_type_t machine_pin_af_type = {
285
442
.make_new = mp_pin_make_new ,
286
443
.locals_dict = (mp_obj_dict_t * )& machine_pin_locals_dict ,
287
444
};
445
+
446
+ STATIC mp_uint_t machine_pin_irq_trigger (mp_obj_t self_in , mp_uint_t new_trigger ) {
447
+ machine_pin_obj_t * self = MP_OBJ_TO_PTR (self_in );
448
+ uint32_t gpio_nr = GPIO_get_instance (self -> gpio );
449
+ machine_pin_irq_obj_t * irq = MP_STATE_PORT (machine_pin_irq_objects [GET_PIN_IRQ_INDEX (gpio_nr , self -> pin )]);
450
+ uint32_t irq_num = self -> pin < 16 ? GPIO_combined_low_irqs [gpio_nr ] : GPIO_combined_high_irqs [gpio_nr ];
451
+ DisableIRQ (irq_num );
452
+ irq -> flags = 0 ;
453
+ irq -> trigger = new_trigger ;
454
+ // Configure the interrupt.
455
+ GPIO_PinSetInterruptConfig (self -> gpio , self -> pin , irq -> trigger );
456
+ // Enable LEVEL1 interrupt.
457
+ EnableIRQ (irq_num );
458
+ // Enable the specific pin interrupt.
459
+ GPIO_PortEnableInterrupts (self -> gpio , 1U << self -> pin );
460
+ return 0 ;
461
+ }
462
+
463
+ STATIC mp_uint_t machine_pin_irq_info (mp_obj_t self_in , mp_uint_t info_type ) {
464
+ machine_pin_obj_t * self = MP_OBJ_TO_PTR (self_in );
465
+ uint32_t gpio_nr = GPIO_get_instance (self -> gpio );
466
+ machine_pin_irq_obj_t * irq = MP_STATE_PORT (machine_pin_irq_objects [GET_PIN_IRQ_INDEX (gpio_nr , self -> pin )]);
467
+ if (info_type == MP_IRQ_INFO_FLAGS ) {
468
+ return irq -> flags ;
469
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS ) {
470
+ return irq -> trigger ;
471
+ }
472
+ return 0 ;
473
+ }
474
+
475
+ STATIC const mp_irq_methods_t machine_pin_irq_methods = {
476
+ .trigger = machine_pin_irq_trigger ,
477
+ .info = machine_pin_irq_info ,
478
+ };
0 commit comments