aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2025-07-14 14:58:49 -0400
committerKevin O'Connor <kevin@koconnor.net>2025-07-22 14:11:17 -0400
commit116b304541f75a7975e7cdfb0689e673a9782d09 (patch)
tree7f500d36749919a6ca2c985a0ad0a2fc6cff8d1d
parent3219712c1715f5d84f23b5b7fc406812bc2bc6db (diff)
downloadkutter-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.c12
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);
}