Skip to content

Commit e6093c0

Browse files
Gadgetoiddpgeorge
authored andcommitted
rp2/rp2_pio: Add support for RP2350A/B variants in PIO interface.
Add support for 32 and 48 pin variants of RP2350. Add new `PIO.gpio_base()` method, mirroring the Pico SDK. Signed-off-by: Phil Howard <phil@gadgetoid.com> Signed-off-by: Damien George <damien@micropython.org>
1 parent a3d1c59 commit e6093c0

2 files changed

Lines changed: 90 additions & 13 deletions

File tree

docs/library/rp2.PIO.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ Constructors
2727
Methods
2828
-------
2929

30+
.. method:: PIO.gpio_base([base])
31+
32+
Query and optionally set the current GPIO base for this PIO instance.
33+
34+
If an argument is given then it must be a pin (or integer corresponding to a pin
35+
number), restricted to either GPIO0 or GPIO16. The GPIO base will then be set to
36+
that pin. Setting the GPIO base must be done before any programs are added or state
37+
machines created.
38+
39+
Returns the current GPIO base pin.
40+
3041
.. method:: PIO.add_program(program)
3142

3243
Add the *program* to the instruction memory of this PIO instance.

ports/rp2/rp2_pio.c

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "py/mperrno.h"
3232
#include "py/mphal.h"
3333
#include "shared/runtime/mpirq.h"
34+
#include "machine_pin.h"
3435
#include "modrp2.h"
3536

3637
#include "hardware/clocks.h"
@@ -54,7 +55,7 @@ typedef struct _rp2_state_machine_obj_t {
5455
PIO pio;
5556
uint8_t irq;
5657
uint8_t sm; // 0-3
57-
uint8_t id; // 0-7
58+
uint8_t id; // 0-7 on RP2040, or 0-11 on RP2350
5859
} rp2_state_machine_obj_t;
5960

6061
typedef struct _rp2_state_machine_irq_obj_t {
@@ -63,11 +64,11 @@ typedef struct _rp2_state_machine_irq_obj_t {
6364
uint8_t trigger;
6465
} rp2_state_machine_irq_obj_t;
6566

66-
static const rp2_state_machine_obj_t rp2_state_machine_obj[8];
67-
static uint8_t rp2_state_machine_initial_pc[8];
67+
static const rp2_state_machine_obj_t rp2_state_machine_obj[NUM_PIOS * 4];
68+
static uint8_t rp2_state_machine_initial_pc[NUM_PIOS * 4];
6869

6970
// These masks keep track of PIO instruction memory used by this module.
70-
static uint32_t rp2_pio_instruction_memory_usage_mask[2];
71+
static uint32_t rp2_pio_instruction_memory_usage_mask[NUM_PIOS];
7172

7273
static const rp2_state_machine_obj_t *rp2_state_machine_get_object(mp_int_t sm_id);
7374
static void rp2_state_machine_reset_all(void);
@@ -104,8 +105,19 @@ static void pio1_irq0(void) {
104105
pio_irq0(pio1);
105106
}
106107

108+
#if NUM_PIOS >= 3
109+
static void pio2_irq0(void) {
110+
pio_irq0(pio2);
111+
}
112+
#endif
113+
107114
// Returns the correct irq0 handler wrapper for a given pio
108115
static inline irq_handler_t rp2_pio_get_irq_handler(PIO pio) {
116+
#if NUM_PIOS >= 3
117+
if (pio == pio2) {
118+
return pio2_irq0;
119+
}
120+
#endif
109121
return pio == pio0 ? pio0_irq0 : pio1_irq0;
110122
}
111123

@@ -172,6 +184,12 @@ void rp2_pio_deinit(void) {
172184
irq_set_enabled(PIO1_IRQ_0, false);
173185
irq_remove_handler(PIO1_IRQ_0, pio1_irq0);
174186
}
187+
#if NUM_PIOS >= 3
188+
if (irq_get_exclusive_handler(PIO2_IRQ_0) == pio2_irq0) {
189+
irq_set_enabled(PIO2_IRQ_0, false);
190+
irq_remove_handler(PIO2_IRQ_0, pio2_irq0);
191+
}
192+
#endif
175193

176194
rp2_state_machine_reset_all();
177195

@@ -180,6 +198,9 @@ void rp2_pio_deinit(void) {
180198
// and their PIO programs should remain intact.
181199
rp2_pio_remove_all_managed_programs(pio0);
182200
rp2_pio_remove_all_managed_programs(pio1);
201+
#if NUM_PIOS >= 3
202+
rp2_pio_remove_all_managed_programs(pio2);
203+
#endif
183204
}
184205

185206
/******************************************************************************/
@@ -212,7 +233,7 @@ static void asm_pio_override_shiftctrl(mp_obj_t arg, uint32_t bits, uint32_t lsb
212233
}
213234
}
214235

215-
static void asm_pio_get_pins(const char *type, mp_obj_t prog_pins, mp_obj_t arg_base, asm_pio_config_t *config) {
236+
static void asm_pio_get_pins(PIO pio, const char *type, mp_obj_t prog_pins, mp_obj_t arg_base, asm_pio_config_t *config) {
216237
if (prog_pins != mp_const_none) {
217238
// The PIO program specified pins for initialisation on out/set/sideset.
218239
if (mp_obj_is_integer(prog_pins)) {
@@ -238,13 +259,21 @@ static void asm_pio_get_pins(const char *type, mp_obj_t prog_pins, mp_obj_t arg_
238259
if (arg_base != mp_const_none) {
239260
// The instantiation of the PIO program specified a base pin.
240261
config->base = mp_hal_get_pin_obj(arg_base);
262+
263+
#if PICO_PIO_USE_GPIO_BASE
264+
// Check the base is within range of the configured gpio_base.
265+
uint gpio_base = pio_get_gpio_base(pio);
266+
if ((gpio_base == 0 && config->base >= 32) || (gpio_base == 16 && config->base < 16)) {
267+
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s_base not within gpio_base range"), type);
268+
}
269+
#endif
241270
}
242271
}
243272

244273
static void asm_pio_init_gpio(PIO pio, uint32_t sm, asm_pio_config_t *config) {
245-
uint32_t pinmask = ((1 << config->count) - 1) << config->base;
246-
pio_sm_set_pins_with_mask(pio, sm, config->pinvals << config->base, pinmask);
247-
pio_sm_set_pindirs_with_mask(pio, sm, config->pindirs << config->base, pinmask);
274+
uint32_t pinmask = ((1 << config->count) - 1) << (config->base - pio_get_gpio_base(pio));
275+
pio_sm_set_pins_with_mask(pio, sm, config->pinvals << (config->base - pio_get_gpio_base(pio)), pinmask);
276+
pio_sm_set_pindirs_with_mask(pio, sm, config->pindirs << (config->base - pio_get_gpio_base(pio)), pinmask);
248277
for (size_t i = 0; i < config->count; ++i) {
249278
gpio_set_function(config->base + i, GPIO_FUNC_PIO0 + pio_get_index(pio));
250279
}
@@ -258,6 +287,9 @@ static const mp_irq_methods_t rp2_pio_irq_methods;
258287
static rp2_pio_obj_t rp2_pio_obj[] = {
259288
{ { &rp2_pio_type }, pio0, PIO0_IRQ_0 },
260289
{ { &rp2_pio_type }, pio1, PIO1_IRQ_0 },
290+
#if NUM_PIOS >= 3
291+
{ { &rp2_pio_type }, pio2, PIO2_IRQ_0 },
292+
#endif
261293
};
262294

263295
static void rp2_pio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -357,6 +389,31 @@ static mp_obj_t rp2_pio_state_machine(size_t n_args, const mp_obj_t *pos_args, m
357389
}
358390
MP_DEFINE_CONST_FUN_OBJ_KW(rp2_pio_state_machine_obj, 2, rp2_pio_state_machine);
359391

392+
#if PICO_PIO_USE_GPIO_BASE
393+
// PIO.gpio_base([base])
394+
static mp_obj_t rp2_pio_gpio_base(size_t n_args, const mp_obj_t *args) {
395+
rp2_pio_obj_t *self = MP_OBJ_TO_PTR(args[0]);
396+
397+
if (n_args > 1) {
398+
// Set gpio_base value.
399+
uint gpio_base = mp_hal_get_pin_obj(args[1]);
400+
401+
// Must be 0 for GPIOs 0 to 31 inclusive, or 16 for GPIOs 16 to 48 inclusive.
402+
if (!(gpio_base == 0 || gpio_base == 16)) {
403+
mp_raise_ValueError("invalid GPIO base");
404+
}
405+
406+
if (pio_set_gpio_base(self->pio, gpio_base) != PICO_OK) {
407+
mp_raise_OSError(MP_EINVAL);
408+
}
409+
}
410+
411+
// Return current gpio_base value.
412+
return pio_get_gpio_base(self->pio) == 0 ? (mp_obj_t)pin_GPIO0 : (mp_obj_t)pin_GPIO16;
413+
}
414+
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_pio_gpio_base_obj, 1, 2, rp2_pio_gpio_base);
415+
#endif
416+
360417
// PIO.irq(handler=None, trigger=IRQ_SM0|IRQ_SM1|IRQ_SM2|IRQ_SM3, hard=False)
361418
static mp_obj_t rp2_pio_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
362419
enum { ARG_handler, ARG_trigger, ARG_hard };
@@ -410,6 +467,9 @@ static mp_obj_t rp2_pio_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
410467
static MP_DEFINE_CONST_FUN_OBJ_KW(rp2_pio_irq_obj, 1, rp2_pio_irq);
411468

412469
static const mp_rom_map_elem_t rp2_pio_locals_dict_table[] = {
470+
#if PICO_PIO_USE_GPIO_BASE
471+
{ MP_ROM_QSTR(MP_QSTR_gpio_base), MP_ROM_PTR(&rp2_pio_gpio_base_obj) },
472+
#endif
413473
{ MP_ROM_QSTR(MP_QSTR_add_program), MP_ROM_PTR(&rp2_pio_add_program_obj) },
414474
{ MP_ROM_QSTR(MP_QSTR_remove_program), MP_ROM_PTR(&rp2_pio_remove_program_obj) },
415475
{ MP_ROM_QSTR(MP_QSTR_state_machine), MP_ROM_PTR(&rp2_pio_state_machine_obj) },
@@ -486,6 +546,12 @@ static const rp2_state_machine_obj_t rp2_state_machine_obj[] = {
486546
{ { &rp2_state_machine_type }, pio1, PIO1_IRQ_0, 1, 5 },
487547
{ { &rp2_state_machine_type }, pio1, PIO1_IRQ_0, 2, 6 },
488548
{ { &rp2_state_machine_type }, pio1, PIO1_IRQ_0, 3, 7 },
549+
#if NUM_PIOS >= 3
550+
{ { &rp2_state_machine_type }, pio2, PIO2_IRQ_0, 0, 8 },
551+
{ { &rp2_state_machine_type }, pio2, PIO2_IRQ_0, 1, 9 },
552+
{ { &rp2_state_machine_type }, pio2, PIO2_IRQ_0, 2, 10 },
553+
{ { &rp2_state_machine_type }, pio2, PIO2_IRQ_0, 3, 11 },
554+
#endif
489555
};
490556

491557
static const rp2_state_machine_obj_t *rp2_state_machine_get_object(mp_int_t sm_id) {
@@ -604,14 +670,14 @@ static mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
604670

605671
// Configure out pins, if needed.
606672
asm_pio_config_t out_config = ASM_PIO_CONFIG_DEFAULT;
607-
asm_pio_get_pins("out", prog[PROG_OUT_PINS], args[ARG_out_base].u_obj, &out_config);
673+
asm_pio_get_pins(self->pio, "out", prog[PROG_OUT_PINS], args[ARG_out_base].u_obj, &out_config);
608674
if (out_config.base >= 0) {
609675
sm_config_set_out_pins(&config, out_config.base, out_config.count);
610676
}
611677

612678
// Configure set pin, if needed.
613679
asm_pio_config_t set_config = ASM_PIO_CONFIG_DEFAULT;
614-
asm_pio_get_pins("set", prog[PROG_SET_PINS], args[ARG_set_base].u_obj, &set_config);
680+
asm_pio_get_pins(self->pio, "set", prog[PROG_SET_PINS], args[ARG_set_base].u_obj, &set_config);
615681
if (set_config.base >= 0) {
616682
sm_config_set_set_pins(&config, set_config.base, set_config.count);
617683
}
@@ -623,7 +689,7 @@ static mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
623689

624690
// Configure sideset pin, if needed.
625691
asm_pio_config_t sideset_config = ASM_PIO_CONFIG_DEFAULT;
626-
asm_pio_get_pins("sideset", prog[PROG_SIDESET_PINS], args[ARG_sideset_base].u_obj, &sideset_config);
692+
asm_pio_get_pins(self->pio, "sideset", prog[PROG_SIDESET_PINS], args[ARG_sideset_base].u_obj, &sideset_config);
627693
if (sideset_config.base >= 0) {
628694
uint32_t count = sideset_config.count;
629695
if (config.execctrl & (1 << PIO_SM0_EXECCTRL_SIDE_EN_LSB)) {
@@ -951,5 +1017,5 @@ static const mp_irq_methods_t rp2_state_machine_irq_methods = {
9511017
.info = rp2_state_machine_irq_info,
9521018
};
9531019

954-
MP_REGISTER_ROOT_POINTER(void *rp2_pio_irq_obj[2]);
955-
MP_REGISTER_ROOT_POINTER(void *rp2_state_machine_irq_obj[8]);
1020+
MP_REGISTER_ROOT_POINTER(void *rp2_pio_irq_obj[NUM_PIOS]);
1021+
MP_REGISTER_ROOT_POINTER(void *rp2_state_machine_irq_obj[NUM_PIOS * 4]);

0 commit comments

Comments
 (0)