Skip to content

Commit 532e7db

Browse files
authored
Merge pull request #4267 from dhalbert/rp2040-digitalinout-fixes
RP2040: change DigitalInOut direction only when necessary; strong drive strength
2 parents 58de611 + d9234ff commit 532e7db

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

ports/raspberrypi/common-hal/digitalio/DigitalInOut.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct(
4343
self->output = false;
4444
self->open_drain = false;
4545

46+
// Set to input. No output value.
4647
gpio_init(pin->number);
4748
return DIGITALINOUT_OK;
4849
}
@@ -75,11 +76,17 @@ digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output(
7576
digitalio_digitalinout_obj_t* self, bool value,
7677
digitalio_drive_mode_t drive_mode) {
7778
const uint8_t pin = self->pin->number;
78-
gpio_set_dir(pin, GPIO_OUT);
79-
// TODO: Turn on "strong" pin driving (more current available).
79+
gpio_disable_pulls(pin);
80+
81+
// Turn on "strong" pin driving (more current available).
82+
hw_write_masked(&padsbank0_hw->io[pin],
83+
PADS_BANK0_GPIO0_DRIVE_VALUE_12MA << PADS_BANK0_GPIO0_DRIVE_LSB,
84+
PADS_BANK0_GPIO0_DRIVE_BITS);
8085

8186
self->output = true;
82-
common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode);
87+
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
88+
89+
// Pin direction is ultimately set in set_value. We don't need to do it here.
8390
common_hal_digitalio_digitalinout_set_value(self, value);
8491
return DIGITALINOUT_OK;
8592
}
@@ -92,10 +99,18 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
9299
void common_hal_digitalio_digitalinout_set_value(
93100
digitalio_digitalinout_obj_t* self, bool value) {
94101
const uint8_t pin = self->pin->number;
95-
if (self->open_drain) {
96-
gpio_set_dir(pin, value ? GPIO_IN : GPIO_OUT);
102+
if (self->open_drain && value) {
103+
// If true and open-drain, set the direction -before- setting
104+
// the pin value, to to avoid a high glitch on the pin before
105+
// switching from output to input for open-drain.
106+
gpio_set_dir(pin, GPIO_IN);
107+
gpio_put(pin, value);
97108
} else {
109+
// Otherwise set the direction -after- setting the pin value,
110+
// to avoid a glitch which might occur if the old value was
111+
// different and the pin was previously set to input.
98112
gpio_put(pin, value);
113+
gpio_set_dir(pin, GPIO_OUT);
99114
}
100115
}
101116

@@ -110,9 +125,6 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode(
110125
const uint8_t pin = self->pin->number;
111126
bool value = common_hal_digitalio_digitalinout_get_value(self);
112127
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
113-
if (self->open_drain) {
114-
gpio_put(pin, false);
115-
}
116128
// True is implemented differently between modes so reset the value to make
117129
// sure it's correct for the new mode.
118130
if (value) {

0 commit comments

Comments
 (0)