Electronic – Why would you enable pullup for a GPIO pin in push-pull mode

gpiopulluppush-pull

In this STM32L486xx HAL User Manual (note: 36 MB!) is an example for GPIO configuration to power an external LED on page 53. The code lines that are confusing me are these two:

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
GPIO_InitStruct.Pull = GPIO_PULLUP; 

So they are using push-pull mode in combination with a pullup. Why would you do that? I can't think of a use case. Either the output is high anyway, then the pullup won't be necessary. Or the output is low, than the pullup will stand no chance and the output signal will still be low, with or without pull up. So is there a reasonable use for this configuration?

Best Answer

Just like the pull-up, the reason to do this is a bit weak. Is it wrong to do this? Certainly not. Should you do this though? Possibly. Does it make much sense for a code example that is doing nothing but flashing an LED? Not really.

This series of ST microcontrollers have their pull-up and pull-down resistors controlled completely independently from anything else, allowing you to indeed do current-wasting configurations like this one, where the pull-up will do nothing when the pin is high, and will waste maybe a hundred µA or two of current (still without doing anything) when low.

There is a reason one might wish to do this, and it is simply to ensure the pin will be pulled to a default state if the mode is changed away from push-pull mode later. While it is true that neither the pull-up or pull-down resistors serve any purpose in push-pull mode, the pull-up resistor at least is likely desirable in all other modes: open-drain, and input. So if you aren't counting every µA, and might be changing the roles of certain pins, it can make sense to leave the pull-up turned on all the time, just to ensure that the pin will never get floated by accident or otherwise glitch when the pin mode of the GPIO pin is switched to something other than push-pull. Indeed, any time you had a pin in push-pull mode and needed to switch it to open-drain or an input mode, you would probably activate the pull-up resistor before actually switching to that mode, so the ability to have the pull-up resistor turned on even when in push-pull mode is certainly useful and important. It is needed to prevent glitching when changing the pin to input or open drain, depending on what is connected to it of course.

Now, it is definitely an odd choice to use it in an example like they have. Just to be absolutely clear, one could (and arguably should in most cases) set GPIO_InitStruct.Pull to GPIO_NOPULL when using the pin in push-pull mode.

Of course, if you do that, you will have to remember to turn on a pull-up or pull-down resistor (if there isn't an external one) should you change the pin mode to something other than push-pull. Perhaps ST is just playing it safe and assuming someone blinking an LED will stand a good chance of overlooking this, at least initially. Or maybe it was just a small oversight. Regardless, it certainly serves no real purpose in the example shown and because of that, I feel it mostly just confuses the point of the documentation here.

Which is why you've come to stack exchange to even ask this question. Maybe someone from ST will update the PDF after reading this. In my opinion, they should, as it is clearly confusing people and that is the last thing one would want documentation to do.

Beyond that, don't read too much into it. You'll run across little oddities like this fairly regularly, but don't start second guessing yourself each time it happens. I think most of us probably like to pretend all our datasheets and documentation and application notes are error-free, with every line of example code and every sentence purposeful and well thought-out. But we're all human, and as long as humans are still writing datasheets and documentation, sometimes you'll find mistakes. Many mistakes you'll come across are relatively benign and result in something that is merely a little strange or unnecessary like this example. These are also the ones that often never get corrected, simply because it doesn't really matter that much and no one can be bothered.

How I handled specific code oddity, and a good way to handle something like this in the future is to consult the actual datasheet of the chip in question. Understand how the port physically works, and then you'll be confident enough that there isn't really a reason to turn on the pull-up in that situation and not worry about it. If you understand how the chip functions, that's all you need. You'll be able to spot, rather than be at the mercy of, any weirdness contained in any example code for the chip, regardless of who wrote it.