diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2025-07-14 14:58:49 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2025-07-22 14:11:17 -0400 |
commit | 116b304541f75a7975e7cdfb0689e673a9782d09 (patch) | |
tree | 7f500d36749919a6ca2c985a0ad0a2fc6cff8d1d | |
parent | 3219712c1715f5d84f23b5b7fc406812bc2bc6db (diff) | |
download | kutter-116b304541f75a7975e7cdfb0689e673a9782d09.tar.gz kutter-116b304541f75a7975e7cdfb0689e673a9782d09.tar.xz kutter-116b304541f75a7975e7cdfb0689e673a9782d09.zip |
avr: Switch to input state prior to enabling pullup in gpio_in_reset()
If switching a pin from output low to input with pullup, there is an
intermediate state of either driven high or high impedance without a
pullup. Similarly, when switching from output high to input without a
pullup, there is an intermediate state of either driven low or high
impedence with a pullup. In both cases it is preferable for the
latter transition.
Also, calculate the final setting prior to making any changes to
reduce the time in that intermediate state.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r-- | src/avr/gpio.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/avr/gpio.c b/src/avr/gpio.c index d10fc2a1..f5225177 100644 --- a/src/avr/gpio.c +++ b/src/avr/gpio.c @@ -70,8 +70,10 @@ void gpio_out_reset(struct gpio_out g, uint8_t val) { irqstatus_t flag = irq_save(); - g.regs->out = val ? (g.regs->out | g.bit) : (g.regs->out & ~g.bit); - g.regs->mode |= g.bit; + uint8_t newmode = g.regs->mode | g.bit; + uint8_t newout = val ? (g.regs->out | g.bit) : (g.regs->out & ~g.bit); + g.regs->out = newout; + g.regs->mode = newmode; irq_restore(flag); } @@ -114,8 +116,10 @@ void gpio_in_reset(struct gpio_in g, int8_t pull_up) { irqstatus_t flag = irq_save(); - g.regs->out = pull_up > 0 ? (g.regs->out | g.bit) : (g.regs->out & ~g.bit); - g.regs->mode &= ~g.bit; + uint8_t newout = pull_up>0 ? (g.regs->out | g.bit) : (g.regs->out & ~g.bit); + uint8_t newmode = g.regs->mode & ~g.bit; + g.regs->mode = newmode; + g.regs->out = newout; irq_restore(flag); } |