pico w: Disentangle "TOTAL_GPIO_COUNT", it's complicated

You might wonder how this fixes a problem with PulseIn, when the
changes aren't to any of those files! PulseIn is implemented in terms of
StateMachine, which had some assumptions about the relation between
the index of a pin object in mcu_pin_global_dict_table and its "pin
number". This was true, until some pins were removed from the
microcontroller module on Pico W.

Closes: #7078
This commit is contained in:
Jeff Epler 2022-10-19 21:03:28 -05:00
parent 31d7c91c85
commit 576a1ac700
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 36 additions and 19 deletions

View File

@ -111,7 +111,7 @@ void alarm_pin_pinalarm_reset(void) {
}
// Reset pins and pin IRQs
for (size_t i = 0; i < TOTAL_GPIO_COUNT; i++) {
for (size_t i = 0; i < NUM_BANK0_GPIOS; i++) {
if (alarm_reserved_pins & (1 << i)) {
gpio_set_irq_enabled(i, GPIO_IRQ_ALL_EVENTS, false);
reset_pin_number(i);

View File

@ -46,7 +46,7 @@ void reset_pin_number_cyw(uint8_t pin_no) {
STATIC uint32_t never_reset_pins;
void reset_all_pins(void) {
for (size_t i = 0; i < TOTAL_GPIO_COUNT; i++) {
for (size_t i = 0; i < NUM_BANK0_GPIOS; i++) {
if ((never_reset_pins & (1 << i)) != 0) {
continue;
}
@ -54,16 +54,17 @@ void reset_all_pins(void) {
}
#if CIRCUITPY_CYW43
if (cyw_ever_init) {
for (size_t i = 0; i < 1; i++) {
cyw43_arch_gpio_put(i, 0);
}
// reset LED and SMPS_MODE to Low; don't touch VBUS_SENSE
// otherwise it is switched to output mode forever!
cyw43_arch_gpio_put(0, 0);
cyw43_arch_gpio_put(1, 0);
}
cyw_pin_claimed = 0;
#endif
}
void never_reset_pin_number(uint8_t pin_number) {
if (pin_number >= TOTAL_GPIO_COUNT) {
if (pin_number >= NUM_BANK0_GPIOS) {
return;
}
@ -71,7 +72,7 @@ void never_reset_pin_number(uint8_t pin_number) {
}
void reset_pin_number(uint8_t pin_number) {
if (pin_number >= TOTAL_GPIO_COUNT) {
if (pin_number >= NUM_BANK0_GPIOS) {
return;
}
@ -110,7 +111,7 @@ void claim_pin(const mcu_pin_obj_t *pin) {
}
bool pin_number_is_free(uint8_t pin_number) {
if (pin_number >= TOTAL_GPIO_COUNT) {
if (pin_number >= NUM_BANK0_GPIOS) {
return false;
}

View File

@ -149,7 +149,7 @@ watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj = {
#endif
// This maps MCU pin names to pin objects.
const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = {
const mp_rom_map_elem_t mcu_pin_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_PTR(&pin_GPIO1) },
{ MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_PTR(&pin_GPIO2) },
@ -193,3 +193,13 @@ const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT] = {
#endif
};
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table);
const mcu_pin_obj_t *mcu_get_pin_by_number(int number) {
for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_pin_global_dict_table); i++) {
mcu_pin_obj_t *obj = MP_OBJ_TO_PTR(mcu_pin_global_dict_table[i].value);
if (obj->base.type == &mcu_pin_type && obj->number == number) {
return obj;
}
}
return NULL;
}

View File

@ -28,9 +28,8 @@
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER___INIT___H
#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h"
#include "peripherals/pins.h"
#define TOTAL_GPIO_COUNT NUM_BANK0_GPIOS
extern const mp_rom_map_elem_t mcu_pin_global_dict_table[TOTAL_GPIO_COUNT];
const mcu_pin_obj_t *mcu_get_pin_by_number(int);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER___INIT___H

View File

@ -48,7 +48,7 @@
#define NO_DMA_CHANNEL (-1)
// Count how many state machines are using each pin.
STATIC uint8_t _pin_reference_count[TOTAL_GPIO_COUNT];
STATIC uint8_t _pin_reference_count[NUM_BANK0_GPIOS];
STATIC uint32_t _current_program_id[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC uint8_t _current_program_offset[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC uint8_t _current_program_len[NUM_PIOS][NUM_PIO_STATE_MACHINES];
@ -71,7 +71,7 @@ STATIC void *_interrupt_arg[NUM_PIOS][NUM_PIO_STATE_MACHINES];
STATIC void rp2pio_statemachine_interrupt_handler(void);
static void rp2pio_statemachine_set_pull(uint32_t pull_pin_up, uint32_t pull_pin_down, uint32_t pins_we_use) {
for (size_t i = 0; i < TOTAL_GPIO_COUNT; i++) {
for (size_t i = 0; i < NUM_BANK0_GPIOS; i++) {
bool used = pins_we_use & (1 << i);
if (used) {
bool pull_up = pull_pin_up & (1 << i);
@ -120,7 +120,7 @@ STATIC void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) {
}
uint32_t pins = _current_sm_pins[pio_index][sm];
for (size_t pin_number = 0; pin_number < TOTAL_GPIO_COUNT; pin_number++) {
for (size_t pin_number = 0; pin_number < NUM_BANK0_GPIOS; pin_number++) {
if ((pins & (1 << pin_number)) == 0) {
continue;
}
@ -161,10 +161,14 @@ STATIC uint32_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pin_cou
if (first_pin != NULL) {
for (size_t i = 0; i < pin_count; i++) {
uint8_t pin_number = first_pin->number + i;
if (pin_number >= TOTAL_GPIO_COUNT) {
if (pin_number >= NUM_BANK0_GPIOS) {
mp_raise_ValueError(translate("Pin count too large"));
}
const mcu_pin_obj_t *pin = mcu_pin_global_dict_table[pin_number].value;
const mcu_pin_obj_t *pin = mcu_get_pin_by_number(pin_number);
if (!pin) {
mp_raise_ValueError_varg(translate("%q in use"), MP_QSTR_Pin);
}
if (exclusive_pin_use || _pin_reference_count[pin_number] == 0) {
assert_pin_free(pin);
}
@ -269,12 +273,15 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
self->pull_pin_up = pull_pin_up;
self->pull_pin_down = pull_pin_down;
for (size_t pin_number = 0; pin_number < TOTAL_GPIO_COUNT; pin_number++) {
for (size_t pin_number = 0; pin_number < NUM_BANK0_GPIOS; pin_number++) {
if ((pins_we_use & (1 << pin_number)) == 0) {
continue;
}
const mcu_pin_obj_t *pin = mcu_get_pin_by_number(pin_number);
if (!pin) {
return false;
}
_pin_reference_count[pin_number]++;
const mcu_pin_obj_t *pin = mcu_pin_global_dict_table[pin_number].value;
// Also claim the pin at the top level when we're the first to grab it.
if (_pin_reference_count[pin_number] == 1) {
if (claim_pins) {