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>
This commit is contained in:
Kevin O'Connor 2025-07-14 14:58:49 -04:00
parent 3219712c17
commit 116b304541

View File

@ -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);
}