Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add open-drain GPIO support. #15282

Merged
merged 6 commits into from
Dec 27, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Wording.
  • Loading branch information
tzarc committed Nov 23, 2021
commit 2aa121b443dd746684f05a8f3b6b099c75b77d38
2 changes: 1 addition & 1 deletion docs/internals_gpio_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The following functions provide basic control of GPIOs and are found in `platfor
| `setPinInputLow(pin)` | Set pin as input with builtin pull-down resistor | N/A (Not supported on AVR) | `palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)` |
| `setPinOutput(pin)` | Set pin as output (alias of `setPinOutputPushPull`) | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` |
| `setPinOutputPushPull(pin)` | Set pin as output, push/pull mode | `DDRB \|= (1<<2)` | `palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)` |
| `setPinOutputOpenDrain(pin)` | Set pin as output, open-drain mode | N/A (Not supported on AVR) | `palSetLineMode(pin, PAL_MODE_OUTPUT_OPENDRAIN)` |
| `setPinOutputOpenDrain(pin)` | Set pin as output, open-drain mode | N/A (Not implemented on AVR) | `palSetLineMode(pin, PAL_MODE_OUTPUT_OPENDRAIN)` |
| `writePinHigh(pin)` | Set pin level as high, assuming it is an output | `PORTB \|= (1<<2)` | `palSetLine(pin)` |
| `writePinLow(pin)` | Set pin level as low, assuming it is an output | `PORTB &= ~(1<<2)` | `palClearLine(pin)` |
| `writePin(pin, level)` | Set pin level, assuming it is an output | `(level) ? PORTB \|= (1<<2) : PORTB &= ~(1<<2)` | `(level) ? palSetLine(pin) : palClearLine(pin)` |
Expand Down
2 changes: 1 addition & 1 deletion platforms/arm_atsam/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ typedef uint8_t pin_t;
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
} while (0)

#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam HAL does not yet implement an open-drain output")
#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam platform does not implement an open-drain output")

#define setPinOutput(pin) setPinOutputPushPull(pin)

Expand Down
4 changes: 2 additions & 2 deletions platforms/avr/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ typedef uint8_t pin_t;
#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low")
#define setPinOutputPushPull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR processors cannot implement an open-drain output")
#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR platform does not implement an open-drain output")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically it is possible to implement an open-drain output on AVR — set the PORTx bit to 0, then write the inverted output value to the DDRx bit. The problem is that it requires either some conditional code in the writePin() implementation, or a separate set of macros like writeOpenDrainPin(), writeOpenDrainPinHigh(), writeOpenDrainPinLow() (with bad consequences if you use a wrong kind of macro for the chosen pin mode).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, but nobody has asked for it, and nobody's using it. Figured it'd be a problem for another day.

#define setPinOutput(pin) setPinOutputPushPull(pin)

#define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
Expand All @@ -46,7 +46,7 @@ typedef uint8_t port_data_t;
#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF))
#define setPortBitOutputPushPull(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF))
#define setPortBitOutputOpenDrain(port, bit) _Static_assert(0, "AVR processors cannot implement an open-drain output")
#define setPortBitOutputOpenDrain(port, bit) _Static_assert(0, "AVR platform does not implement an open-drain output")
#define setPortBitOutput(port, bit) setPortBitOutputPushPull((port), (bit))

#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
Expand Down