P9_41 as input, strange behavior

We have a VERY SIMPLE situation where we are reading a pushbutton status on P9_41 with the ARM processor running some simple C code. Here’s code that’s pulled from the complete program to show how we set up the GPIO, etc.

	// Note: This code has GPIO's configured to buttons in a manner that works properly

	#include <stdio.h>
	#include <unistd.h>
	#include <string.h>
	#include <stdlib.h>
	#include <fcntl.h>
	
	main()
	{
	system("config-pin P9_41 gpio");  // Process on/off switch input, GPIO20
	system("config-pin P8_15 gpio");  // run/stop input, GPIO47
	
	int KeepGoing;
	char value_str[7];
	
	FILE * PulseButton_dir = fopen("/sys/bus/gpio/devices/gpiochip1/gpio/gpio47/direction","w"); // GPIO47
	FILE * PulseButton_val = fopen("/sys/bus/gpio/devices/gpiochip1/gpio/gpio47/value","r");
	    
	FILE * RunStopButton_dir = fopen("/sys/bus/gpio/devices/gpiochip0/gpio/gpio20/direction","w"); // GPIO20
	FILE * RunStopButton_val = fopen("/sys/bus/gpio/devices/gpiochip0/gpio/gpio20/value","r"); 
	
	fprintf(PulseButton_dir, "in\n");
	fflush(PulseButton_dir);
	fclose(PulseButton_dir);
		
	fprintf(RunStopButton_dir, "in\n");
	fflush(RunStopButton_dir);
	fclose(RunStopButton_dir);    

   KeepGoing = 1;
	      	
	      	while(KeepGoing)
	      	{
	      	printf("Push the pushbutton to stop loop.\n");
	      	fread(&value_str, 6, 1, PulseButton_val);   
		    printf("PB input reads. %c\n",value_str[0]);
		    if (value_str[0] == '0') 
		    	{
		        	printf("Detected button push. %c\n",value_str[0]);
    				usleep(3*1000*1000);
		        }
		    
		    rewind(PulseButton_val);
		    usleep(1*1000*500);
		    
	      	}
   
	
	}

When we run this and push the push button, the ‘push’ is detected and when we let go, that is detected too and the code continues to loop until we break out of it. However, presses are detected randomly after that even when we don’t touch the pushbutton. It doesn’t even settle down like you might expect if it was a switch bounce issue. Initially we suspected a hardware problem and ultimately built a completely new rev of our board and assembly. It continued to have this behavior with the new assemblies.

On a whim, I switched the pushbutton to GPIO P8_15 (as shown in the code above) and the pushbutton ‘press’ is only detected when we press the button. There are no random pushbutton detections.

So, my question is this…

Is there something unique about P9_41 that would cause it to randomly appear to be 0/grounded?

Here is the output of version.sh

root@beaglebone:/boot# /opt/scripts/tools/version.sh
git:/opt/scripts/:[e4e4854ef8ff9ada5c85553376043ee7679167ca]
eeprom:[A335BNLTBWA52027BBWG0227]
model:[TI_AM335x_BeagleBone_Black_Wireless]
dogtag:[BeagleBoard.org Debian Buster IoT Image 2021-02-15]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot SPL 2019.04-00002-gc9b3922522 (Aug 24 2020 - 16:42:18 -0500)]:[location: dd MBR]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2019.04-00002-gc9b3922522]:[location: dd MBR]
UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0]
UBOOT: Loaded Overlay:[BB-ADC-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-BBBW-WL1835-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-BONE-eMMC1-01-00A0.bb.org-overlays]
kernel:[4.19.94-ti-r64]
nodejs:[v10.23.1]
/boot/uEnv.txt Settings:
uboot_overlay_options:[enable_uboot_overlays=1]
uboot_overlay_options:[disable_uboot_overlay_video=1]
uboot_overlay_options:[disable_uboot_overlay_audio=1]
uboot_overlay_options:[uboot_overlay_pru=AM335X-PRU-RPROC-4-19-TI-00A0.dtbo]
uboot_overlay_options:[enable_uboot_cape_universal=1]
pkg check: to individually upgrade run: [sudo apt install --only-upgrade ]
pkg:[bb-cape-overlays]:[4.14.20210809.0-0~buster+20210816]
pkg:[bb-customizations]:[1.20210810.1-0~buster+20210810]
pkg:[bb-usb-gadgets]:[1.20200504.0-0~buster+20200504]
pkg:[bb-wl18xx-firmware]:[1.20200813.1-0~buster+20200813]
pkg:[kmod]:[26-1]
pkg:[librobotcontrol]:[1.0.5-git20200715.0-0~buster+20200716]
pkg:[firmware-ti-connectivity]:[20190717-2rcnee1~buster+20200305]
groups:[debian : debian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal input bluetooth netdev i2c gpio admin spi iio docker tisdk weston-launch xenomai cloud9ide pwm eqep remoteproc]
cmdline:[console=ttyO0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet]
dmesg | grep remote
[ 56.095552] Bluetooth: hci0: change remote baud rate command in firmware
[ 74.733402] remoteproc remoteproc0: wkup_m3 is available
[ 74.764609] remoteproc remoteproc0: powering up wkup_m3
[ 74.764644] remoteproc remoteproc0: Booting fw image am335x-pm-firmware.elf, size 217148
[ 74.764930] remoteproc remoteproc0: remote processor wkup_m3 is now up
[ 77.900094] remoteproc remoteproc1: 4a334000.pru is available
[ 77.915984] remoteproc remoteproc2: 4a338000.pru is available
dmesg | grep pru
[ 77.900094] remoteproc remoteproc1: 4a334000.pru is available
[ 77.900296] pru-rproc 4a334000.pru: PRU rproc node pru@4a334000 probed successfully
[ 77.915984] remoteproc remoteproc2: 4a338000.pru is available
[ 77.916181] pru-rproc 4a338000.pru: PRU rproc node pru@4a338000 probed successfully
dmesg | grep pinctrl-single
[ 1.021740] pinctrl-single 44e10800.pinmux: 142 pins, size 568
[ 1.493430] pinctrl-single 44e10800.pinmux: pin PIN74 already requested by 481a6000.serial; cannot claim for leds
[ 1.503883] pinctrl-single 44e10800.pinmux: pin-74 (leds) status -22
[ 1.510303] pinctrl-single 44e10800.pinmux: could not request pin 74 (PIN74) from group pinmux_bt_pins on device pinctrl-single
dmesg | grep gpio-of-helper
[ 1.035181] gpio-of-helper ocp:cape-universal: ready
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
END

P9_41 and P9_42 are special as there are two pins each:

Care must be taken to make sure the ‘other’ is configured as an input…

Regards,

this is known broken kernel,

sudo apt update
sudo apt install bbb.io-kernel-4.19-ti-am335x
sudo reboot

Regards,

Interesting…thank you!

So, it looks like the ‘other’ P9_41 input is P9_41B and is gpio3[20] aka gpio116.

I tried adding this code

FILE * PulseButtonB_dir = fopen("/sys/bus/gpio/devices/gpiochip3/gpio/gpio116/direction","w"); // GPIO116
FILE * PulseButtonB_val = fopen("/sys/bus/gpio/devices/gpiochip3/gpio/gpio116/value","r");

fprintf(PulseButtonB_dir, "in\n");
fflush(PulseButtonB_dir);
fclose(PulseButtonB_dir);

to configure the ‘other’ as input but I get the random ghost button pushes still.

FYI - I completed the suggested kernel updates and still get the ghost button pushes.

@WalterCEden: Do you have long cables wired to the button (working as an antenna)? Do you force the line to a certain state (pull-up/pull-down)? Did you try the hardware GPIO DeBouncing feature?

There’s just one P9_41 header pin, but two CPU balls connected to it.

When pinmuxing by libpruio the other CPU ball gets auto-handled. The user needs not care about that special case.

I’m fairly certain that this is not a hardware issue. It is a long, multiconductor cable but it is shielded. We have observed the signals with a scope and other is only minimal/acceptable noise. We use a 1K resistor for pull-up. I believe it has to do with the two CPU balls connected to the same pin. I have tried to configure both i/o points on the CPU as inputs as @RobertCNelson indicated but the problem persists. I may not have done that correctly and would appreciate some feedback.

I’ll Google the hardware GPIO DeBouncing feature. I am not familiar with that.

As for libpruio, that’s a good feature and good to know. We are too deep along and facing some core deadlines so we cannot make a change like that right now.

Another bit of info on why I’m fairly confident that it’s not a problem with our hardware. I have connected the input from the pushbutton to another GPIO, pin P8_15, and the pushbutton functions perfectly when connected to it. ( We bring P9_41 and P8_15 out to Phoenix right-angle screw terminal connectors at our custom board’s edge. So it makes it easy to change where the PB connects.) If worse comes to worse, I’ll do some surgery on the board and route the terminal to another GPIO line on P8. We’re out of GPIO on P9.

Find registers DEBOUNCENABLE and DEBOUNCINGTIME in the GpioSet class documentation, and details in the ARM Reference Guide, chapter 25.

Note: this features isn’t supported by any kernel, AFAIK. Only libpruio makes it available for the users.

Just to close this out somewhat…I gave up on P9_41 and rerouted our board to use P8_16 instead. I’m still interested in how to get P9_41a and P9_41b working reliably but haven’t found any good examples on the web to help with this under C.

There are multiple pieces here:

A) P9_41 from Page 11 goes to CLKOUT2 on Page 3

B) CLKOUT2 goes to two different IO pins:

  1. Ball D14/GPIO0_20 on Page 3
  2. Ball D13/GPIO3_20 on Page 4

C) So, you need to make sure that both GPIO0_20 and GPIO3_20 are set to GPIO and input.

D) You may also need to make sure that one of them has a pullup/pulldown enabled so the pin isn’t just floating when nothing is connected.

E) If you want to check if one of the pins or other is causing the issue, remove one of R19 or R20 on Page 3 (surely easier than routing something to P8).

Hope this helps.

Thanks. What document are you referring to?

I had to move forward so I have actually changed from P9_41 to use P8_16. But I’d still like to know how to use P9_41!

Sorry. I’m referring to the BBB schematic PDF here:

Thanks! I am actually using a BeagleBone Black Wireless but I found the schematic for that on Github. Its a little different but has the same issue. I had tried to configure both those GPIOs as inputs but it didn’t work so I punted and changed to P8_16.

Well, as far as I can tell, they work. After installing @RobertCNelson 's new kernel, here’s what I see:

root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: default Direction: in Value: 0
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 0
root@beaglebone:~# config-pin -l P9_41
default gpio gpio_pu gpio_pd gpio_input timer pruin
root@beaglebone:~# config-pin -l P9_91
default gpio gpio_pu gpio_pd gpio_input qep pruout pruin
root@beaglebone:~# config-pin P9_41 gpio_pu
root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: gpio_pu Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: gpio_pu Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: gpio_pu Direction: in Value: 1
root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: gpio_pu Direction: in Value: 1
root@beaglebone:~# config-pin P9_41 gpio_pd
root@beaglebone:~# config-pin -q P9_41
P9_41 Mode: gpio_pd Direction: in Value: 0
root@beaglebone:~# config-pin -q P9_91
P9_91 Mode: default Direction: in Value: 0

If that doesn’t work for you, something is either broken on your board or in the way the BBB Wireless has things connected.

Now I am really confused…I see you are using P9_91 and that works on my BBB Wireless. How did you know to use P9_91? I haven’t seen that in any documentation so far. Where did I miss it?

Walter

P9_91 (and P9_92) are special nodes names the Machinekit developers came up years ago on our 3.8.x kernel, for the “other” pins of P9_41/P9_42, it’s only documented in the dts…

Regards,

I suspect I probably read the “config-pin” script itself, at some point.

As much as I love the BBB hardware and its advanced documentation, I do find myself having to dig through the advanced documentation a lot. I’m grateful that I can do this unlike for the Raspberry Pi. I’m used to it from being an embedded developer for a lot of years, but the fact that I have to do this so much is suboptimal.

Sadly, the documentation and resources for Beaglebone beginners are definitely far inferior to both the Arduino and Raspbery Pi communities.

BTW, instead of using buffered file I/O (fopen, fread), which is not really recommended for sysfs attributes (which do not behave quite like normal files), you may want to use this very simple library I wrote for sysfs gpio: GitHub - mvduin/sysfs-gpio: Simple library for sysfs-based gpio

It also allows for receiving events on gpio edges to avoid polling.

1 Like

Also note that mode “gpio” specifically means “gpio with internal pull-up/down disabled”. To keep inputs from floating it is generally preferred to explicitly use “gpio_pu” or “gpio_pd” to configure gpio with internal pull-up or pull-down respectively, or just leave the pins on mode “default”, which for most pins is equivalent to either gpio_pu or gpio_pd (except for P9.19-20 which default to i2c and P8.31-46 which default to gpio with internal pull disabled because these pins have external pull).

If you do choose to disable internal pull, then make sure that the pin is always driven push-pull by external hardware or has external pull-up or pull-down.

For expansion header pins which connect to two SoC pins each (P9.41, P9.42, and P9.15), beware that both of these SoC pins have individually configurable internal pull. Take care to ensure these are not configured to conflict with each other or with external pull-up/down (if any).

Floating pins or pull-up/down conflicts can result in undefined logic levels and unpredictable behaviour, which sounds about right for your problem description.