Difference in pinMode behaviour between Nano and Nano Every

Apologies if this is a known thing or has been addressed elsewhere. It is new to me.

On the Arduino Nano, when a pin is set to INPUT_PULLUP and then to OUTPUT, it remains high. This is useful if you need to change from high impedance to driven mode without inadvertently pulling the pin low momentarily as would happen if you go directly from INPUT to OUTPUT and then digitalWrite the pin high.

On the Nano Every however, going from INPUT_PULLUP to OUTPUT pulls the pin low (see attached scope traces).

I’m guessing this is to do with the 328 using the same register for pullup and output, while the 4809 has separate registers for the pullup (PINnCTRL) and pin output (OUT).

Code can of course be adapted to fix this behaviour but isn’t this a compatibility issue? Can anyone comment?

The code used to obtain the scope traces is below:

#define SYNC_PIN          6         // Indicates which part of sketch is executing.
#define TEST_PIN          12        // Pin being analysed.
#define SYNC_PERIOD       40        // SYNC_PIN pulse period (us).
#define TEST_TIME         100       // Time TEST_PIN is held in a particular state (us).

void setup() {
    pinMode(TEST_PIN, INPUT);
    pinMode(SYNC_PIN, OUTPUT);
}

void loop() {
    pulseSync(1);                   // Pulse SYNC_PIN once.
    pinMode(TEST_PIN, OUTPUT);      // Enable TEST_PIN drivers.
    digitalWrite(TEST_PIN, HIGH);   // Pulse TEST_PIN just to show it's alive.
    delayMicroseconds(TEST_TIME/2);
    digitalWrite(TEST_PIN, LOW);    // Back to LOW.
    delayMicroseconds(TEST_TIME/2);
    pinMode(TEST_PIN, INPUT);       // TEST_PIN back to high-Z.

    pulseSync(2);                   // Pulse SYNC_PIN twice.
    pinMode(TEST_PIN, INPUT_PULLUP);// Logic analyser/scope shows HIGH.
    delayMicroseconds(TEST_TIME);

    pulseSync(3);                   // Pulse SYNC_PIN thrice.
    pinMode(TEST_PIN, OUTPUT);      // On a Nano, TEST_PIN is driven HIGH, on
    delayMicroseconds(TEST_TIME);   // a Nano Every it is driven LOW.
    pinMode(TEST_PIN, INPUT);       // TEST_PIN back to high-Z.
    delayMicroseconds(TEST_TIME);
}


void pulseSync(int n) {               // Pulses SYNC_PIN high n times.
    while (0 != n--) {
        digitalWrite(SYNC_PIN, HIGH);
        delayMicroseconds(SYNC_PERIOD/2);
        digitalWrite(SYNC_PIN, LOW);
        delayMicroseconds(SYNC_PERIOD/2);
    }
}

On the Nano Every however, going from INPUT_PULLUP to OUTPUT pulls the pin low (see attached scope traces).

Ah. You’ve never done digitalWrite(TEST_PIN, HIGH), so the port output register is 0, and when it’s changed to output, the port output register overrides the pullup.
You can probably make it compatible for both by adding a digitalWrite(TEST_PIN, HIGH) somewhere in initialization. The Every code doesn’t actually change anything other than the direction when you do the pinMode(), so it’s not actively pulling the pin low.

I suppose that pinMode(x, INPUT_PULLUP) on every could set the output register high as well, for compatibiltiy’s sake.

westfw:
I suppose that pinMode(x, INPUT_PULLUP) on every could set the output register high as well, for compatibiltiy's sake.

Indeed. Since the Nano Every is marketed as "pin-compatible" with the Nano, there is an implicit suggestion (and expectation) that code, at least simple code which does not do direct register manipulation, will behave identically on both.