Change default state of GPIO pin

I have a beeper which is controlled by GPIO P9.12. The problem is that the default state of this pin is high (I think this is the problem). So I have a long and annoying beep when the BBB boots. This stops when my programm is loaded, then everything works as it should.

Is there a way to set the default state of this pin to low?



Not that I know of. The device tree can change the pin config to default low but that does not take effect till boot up so there would still be several seconds in the HW default condition. I just recently went through something similar where I had to redesign a lot of stuff on my own PCB since there are quite a few pins that seem to have driven states that were at odds with my design. I was considering going through my existing pin-map document and noting the power-on (pre-device-tree) states of any pins that are driven / pulled one way or the other.

Dont forget you can rebuild u-boot and change the pin states so that they are in the correct state for you before the kernel is loaded.


Is it high (IE. driven) or is it just floating? To quote the TI Technical Reference: “At reset, all the GPIO related pins are configured as input and output capabilities are disabled.” Unless the boot process or some program sets your pin up as an output, then it would just float in a high impedance state until your device tree stuff says otherwise. Does your peripheral device make that loud beep if it is powered but disconnected from P9.12?

If so, then you could change your circuit so it needs to be actively driven or sunk with a maximum of about 4 ma. (To stay within the current limits of a GPIO pin.) That could be as simple as adding a weak pulldown resistor. I would start with a 10K and watch with a scope during startup to see if it ever is driven high.

You need to understand the current and voltage characteristics of anything you attach to a GPIO pin because you can burn up a GPIO (or even the whole chip) just by trying to drive an LED without a transistor or IC buffer.

Thanks for the reply! The beeper is controlled by a transistor (limited with a resistor) so the current is within the margins.

I found a script to check the state of a pin: findGPIO.js The output is;
P9_12 (gpio 60) mode: 7 (gpio1_28) 0x078 pullup Receiver Active

I checked other pins with this script, and P9_16 has this output;
P9_16 (gpio 51) mode: 7 (gpio1_19) 0x04c pulldown Receiver Active

I temporarely connected the base of the transistor to P9_16, and with this pin everything works perfectly. I however prefer to use pin P9_12 because of my circuit.

Is there a way to solve this by software, or will a simple pull down resistor do the trick?


If there is a pullup then your pulldown will have to be several times stronger to make sure that the floating value becomes a logic low. You now have an effective voltage divider with a pullup / pulldown configuration. Fighting against the configured on-chip pullup is going to mean that to output a high you're going to need many times the drive current you would normally need as you sink current into that low-value pulldown resistor.

Not sure what your threshold on the buzzer is but if the pullup is say 30 to 50K then to get a solid 10% default low on the pin you'd need a 3 to 5K resistor on the pulldown. That would be a 1.1 to 0.6mA load on the pin when it swings high. You're also burning 0.1mA when the pin floats since the voltage divider will always be present. That may or may not impact your design.

Assuming I'm thinking of this correctly.

There must be a way to set pullup/pulldown at boot time. Fighting against the pullup is a possibility, but that means that I have to add a "strong"pull down resistor, only for the occasional bootup.

@Marc I didn’t see your message. I think rebuilding u-boot is the way to go. I will look into that now.

I would not fight the enabled pullup with my own pulldown: Either change your control program and circuit to take high as inactive, or change the boot software to program that GPIO with no pull resistor (so you can add your own external pulldown) or program that GPIO with the internal pulldown enabled.

Fighting the internal pullup with a higher-current pulldown is just asking for trouble.

@Guy I have been away for a bit thus my late reaction.

Can you give me a hint how to change the pullup to pulldown at bootup?

I think you have to change it in uboot, but that is beyond my Linux expertise. Look at your original question’s other replies. I think somebody explained how to do that. The register programming info you need is all in the am335x technical reference manual, but I have only manipulated the I/O pins in user space.

I found this thread on I think I will go for the solution from alexan_e, making a reversed circuit with two transistors. It only costs one transistor more.

I have tried changing pull-up to pull-down with uboot, but that didn’t work for me.

Thanks for all the help!