Pullup resistors on SparkFun 8266 Thing Dev

I recently purchased two SparkFun 8266 Thing Dev boards, but a couple of the digital pins are acting weird. I’m doing a pinMode(x, INPUT_PULLUP) on pins 15 and 16, but they’re acting as if I had called pinMode(x, INPUT). All of the other digital pins are acting as expected; it’s just 15 & 16 that are wonky. Doing a digitalRead(15) returns FALSE. Tying it to 3.3v changes it to TRUE, but if I let it float again, it remains TRUE. Momentarily grounding it, gives FALSE again. Pin 16 behaves almost the same way, except that it starts out TRUE. If I put an external 10k pullup on each of the two pins, they act as expected.

I thought that perhaps my soldering my headers onto the board had damaged something. But I took the second board out of its bag and tested it “naked”, and the same two pins are also behaving as if they’re in INPUT mode, not INPUT_PULLUP. Again, If I put an external 10k pullup on each of the two pins, they act as expected.

So is there something special about pins 15 and 16, or did I get I get two defective boards? Below is the code I used to test the boards:

#define PIN_LIST  0, 2, 4, 5, 12, 13, 14, 15, 16
#define PIN_MODE INPUT_PULLUP

// Create a list of pin numbers
int pinNum[] = { PIN_LIST };

#define NUM_PINS (sizeof(pinNum)/sizeof(int))

// We also need an array to keep track of previous pin states
bool prevState[NUM_PINS];

void setup()
{
  bool pinState;
  
  Serial.begin(115200);
  Serial.println("\n\n");
  Serial.printf("Pin mode: %s\n", PIN_MODE==INPUT ? "INPUT" : "INPUT_PULLUP");
  
  // Initialize pin I/O & display initial state of each pin
  for (int i=0; i< NUM_PINS; i++)
  {
    pinMode(pinNum[i], PIN_MODE);
    prevState[i] = digitalRead(pinNum[i]);
    Serial.printf("Pin %02u Initial: %s\n", pinNum[i], prevState[i] ? "HIGH" : "LOW ");
  }

  // Look for and display state changes
  while(true)
  {
    for (int i=0; i< NUM_PINS; i++)
    {
      pinState = digitalRead(pinNum[i]);
      if (pinState != prevState[i])
      {
        Serial.printf("Pin %02u Changed: %s\n", pinNum[i], pinState ? "HIGH" : "LOW ");
        prevState[i] = pinState;
      }
      delay(100);
    }
  }

  // Since the above loop is infinite; execution will never reach this line.

}

void loop()
{
  // Since the setup function never ends,
  // this function will never be called.

}

GPIO 15 and 16 have a special function during boot, hence limited function for internal pull-up:

https://randomnerdtutorials.com/esp8266 … nce-gpios/

https://tttapa.github.io/ESP8266/Chap04 … oller.html

Ahah! Thank you so much!

Best Regards,

Ken