Managing the GPIO pins on a BeagleBone black
Categories
Tags
Recent articles
Ubuntu 16.10 LXC host on ZFS Root, with EFI and Time Machine
How to connect any serial device to the internet
I'm now playing with a BeagleBone Black, but at the time of writing the state of the GPIO pin management is pretty dire. The latest kernel (3.8.13) changed the rules for how GPIO pins are accessed and for a device like the Beaglebone, where pins can have different states, the results are complex.
The best resources I have found are here:
- http://derekmolloy.ie/gpios-on-the-beaglebone-black-using-device-tree-overlays/"
- http://derekmolloy.ie/beaglebone/beaglebone-gpio-programming-on-arm-embedded-linux/
/sys/class/gpio
and /sys/kernel/debug
,
decode the mux data, identify the pin mode... argh. I'm sure it will become easier
with time.
My contribution is this perl script:
#!/usr/bin/perl # List or modify the GPIO pins on BeagleBone Black # # "bbpins.pl" for help # # CSV data derived from Derek Molloy's pin spreadsheet # # This code is in the public domain use strict; use Text::CSV; my $base = 0x44e10000; my $gpiobase = "/sys/class/gpio/gpio"; my $ctrlfile = "/sys/class/gpio/"; my $muxfile = "/sys/kernel/debug/pinctrl/44e10800.pinmux/pins"; my $csv = Text::CSV->new(); my $data = <<EOD; P8_01,,,,DGND,,,,,,,,,, P8_02,,,,DGND,,,,,,,,,, P8_03,6,0x818/018,38,GPIO1_6,gpio1[6],,,,,,mmc1_dat6,gpmc_ad6,R9,Used on Board (Group: pinmux_emmc2_pins) P8_04,7,0x81c/01c,39,GPIO1_7,gpio1[7],,,,,,mmc1_dat7,gpmc_ad7,T9,Used on Board (Group: pinmux_emmc2_pins) P8_05,2,0x808/008,34,GPIO1_2,gpio1[2],,,,,,mmc1_dat2,gpmc_ad2,R8,Used on Board (Group: pinmux_emmc2_pins) P8_06,3,0x80c/00c,35,GPIO1_3,gpio1[3],,,,,,mmc1_dat3,gpmc_ad3,T8,Used on Board (Group: pinmux_emmc2_pins) P8_07,36,0x890/090,66,TIMER4,gpio2[2],,,,,timer4,,gpmc_advn_ale,R7, P8_08,37,0x894/094,67,TIMER7,gpio2[3],,,,,timer7,,gpmc_oen_ren,T7, P8_09,39,0x89c/09c,69,TIMER5,gpio2[5],,,,,timer5,,gpmc_be0n_cle,T6, P8_10,38,0x898/098,68,TIMER6,gpio2[4],,,,,timer6,,gpmc_wen,U6, P8_11,13,0x834/034,45,GPIO1_13,gpio1[13],,,eQEP2B_in,mmc2_dat1,mmc1_dat5,lcd_data18,gpmc_ad13,R12, P8_12,12,0x830/030,44,GPIO1_12,gpio1[12],,,EQEP2A_IN,MMC2_DAT0,MMC1_DAT4,LCD_DATA19,GPMC_AD12,T12, P8_13,9,0x824/024,23,EHRPWM2B,gpio0[23],,,ehrpwm2B,mmc2_dat5,mmc1_dat1,lcd_data22,gpmc_ad9,T10, P8_14,10,0x828/028,26,GPIO0_26,gpio0[26],,,ehrpwm2_tripzone_in,mmc2_dat6,mmc1_dat2,lcd_data21,gpmc_ad10,T11, P8_15,15,0x83c/03c,47,GPIO1_15,gpio1[15],,,eQEP2_strobe,mmc2_dat3,mmc1_dat7,lcd_data16,gpmc_ad15,U13, P8_16,14,0x838/038,46,GPIO1_14,gpio1[14],,,eQEP2_index,mmc2_dat2,mmc1_dat6,lcd_data17,gpmc_ad14,V13, P8_17,11,0x82c/02c,27,GPIO0_27,gpio0[27],,,ehrpwm0_synco,mmc2_dat7,mmc1_dat3,lcd_data20,gpmc_ad11,U12, P8_18,35,0x88c/08c,65,GPIO2_1,gpio2[1],mcasp0_fsr,,,mmc2_clk,gpmc_wait1,lcd_memory_clk,gpmc_clk_mux0,V12, P8_19,8,0x820/020,22,EHRPWM2A,gpio0[22],,,ehrpwm2A,mmc2_dat4,mmc1_dat0,lcd_data23,gpmc_ad8,U10, P8_20,33,0x884/084,63,GPIO1_31,gpio1[31],,,,,mmc1_cmd,gpmc_be1n,gpmc_csn2,V9,Used on Board (Group: pinmux_emmc2_pins) P8_21,32,0x880/080,62,GPIO1_30,gpio1[30],,,,,mmc1_clk,gpmc_clk,gpmc_csn1,U9,Used on Board (Group: pinmux_emmc2_pins) P8_22,5,0x814/014,37,GPIO1_5,gpio1[5],,,,,,mmc1_dat5,gpmc_ad5,V8,Used on Board (Group: pinmux_emmc2_pins) P8_23,4,0x810/010,36,GPIO1_4,gpio1[4],,,,,,mmc1_dat4,gpmc_ad4,U8,Used on Board (Group: pinmux_emmc2_pins) P8_24,1,0x804/004,33,GPIO1_1,gpio1[1],,,,,,mmc1_dat1,gpmc_ad1,V7,Used on Board (Group: pinmux_emmc2_pins) P8_25,0,0x800/000,1,GPIO1_0,gpio1[0],,,,,,mmc1_dat0,gpmc_ad0,U7,Used on Board (Group: pinmux_emmc2_pins) P8_26,31,0x87c/07c,61,GPIO1_29,gpio1[29],,,,,,,gpmc_csn0,V6, P8_27,56,0x8e0/0e0,86,GPIO2_22,gpio2[22],,,,,,gpmc_a8,lcd_vsync,U5,Allocated (Group: nxp_hdmi_bonelt_pins) P8_28,58,0x8e8/0e8,88,GPIO2_24,gpio2[24],,,,,,gpmc_a10,lcd_pclk,V5,Allocated (Group: nxp_hdmi_bonelt_pins) P8_29,57,0x8e4/0e4,87,GPIO2_23,gpio2[23],,,,,,gpmc_a9,lcd_hsync,R5,Allocated (Group: nxp_hdmi_bonelt_pins) P8_30,59,0x8ec/0ec,89,GPIO2_25,gpio2[25],,,,,,gpmc_a11,lcd_ac_bias_en,R6,Allocated (Group: nxp_hdmi_bonelt_pins) P8_31,54,0x8d8/0d8,10,UART5_CTSN,gpio0[10],uart5_ctsn,,uart5_rxd,mcasp0_axr1,eQEP1_index,gpmc_a18,lcd_data14,V4,Allocated (Group: nxp_hdmi_bonelt_pins) P8_32,55,0x8dc/0dc,11,UART5_RTSN,gpio0[11],uart5_rtsn,,mcasp0_axr3,mcasp0_ahclkx,eQEP1_strobe,gpmc_a19,lcd_data15,T5,Allocated (Group: nxp_hdmi_bonelt_pins) P8_33,53,0x8d4/0d4,9,UART4_RTSN,gpio0[9],uart4_rtsn,,mcasp0_axr3,mcasp0_fsr,eQEP1B_in,gpmc_a17,lcd_data13,V3,Allocated (Group: nxp_hdmi_bonelt_pins) P8_34,51,0x8cc/0cc,81,UART3_RTSN,gpio2[17],uart3_rtsn,,mcasp0_axr2,mcasp0_ahclkr,ehrpwm1B,gpmc_a15,lcd_data11,U4,Allocated (Group: nxp_hdmi_bonelt_pins) P8_35,52,0x8d0/0d0,8,UART4_CTSN,gpio0[8],uart4_ctsn,,mcasp0_axr2,mcasp0_aclkr,eQEP1A_in,gpmc_a16,lcd_data12,V2,Allocated (Group: nxp_hdmi_bonelt_pins) P8_36,50,0x8c8/0c8,80,UART3_CTSN,gpio2[16],uart3_ctsn,,,mcasp0_axr0,ehrpwm1A,gpmc_a14,lcd_data10,U3,Allocated (Group: nxp_hdmi_bonelt_pins) P8_37,48,0x8c0/0c0,78,UART5_TXD,gpio2[14],uart2_ctsn,,uart5_txd,mcasp0_aclkx,ehrpwm1_tripzone_in,gpmc_a12,lcd_data8,U1,Allocated (Group: nxp_hdmi_bonelt_pins) P8_38,49,0x8c4/0c4,79,UART5_RXD,gpio2[15],uart2_rtsn,,uart5_rxd,mcasp0_fsx,ehrpwm0_synco,gpmc_a13,lcd_data9,U2,Allocated (Group: nxp_hdmi_bonelt_pins) P8_39,46,0x8b8/0b8,76,GPIO2_12,gpio2[12],,,,eQEP2_index,,gpmc_a6,lcd_data6,T3,Allocated (Group: nxp_hdmi_bonelt_pins) P8_40,47,0x8bc/0bc,77,GPIO2_13,gpio2[13],,,pr1_edio_data_out7,eQEP2_strobe,,gpmc_a7,lcd_data7,T4,Allocated (Group: nxp_hdmi_bonelt_pins) P8_41,44,0x8b0/0b0,74,GPIO2_10,gpio2[10],,,,eQEP2A_in,,gpmc_a4,lcd_data4,T1,Allocated (Group: nxp_hdmi_bonelt_pins) P8_42,45,0x8b4/0b4,75,GPIO2_11,gpio2[11],,,,eQEP2B_in,,gpmc_a5,lcd_data5,T2,Allocated (Group: nxp_hdmi_bonelt_pins) P8_43,42,0x8a8/0a8,72,GPIO2_8,gpio2[8],,,,ehrpwm2_tripzone_in,,gpmc_a2,lcd_data2,R3,Allocated (Group: nxp_hdmi_bonelt_pins) P8_44,43,0x8ac/0ac,73,GPIO2_9,gpio2[9],,,,ehrpwm0_synco,,gpmc_a3,lcd_data3,R4,Allocated (Group: nxp_hdmi_bonelt_pins) P8_45,40,0x8a0/0a0,70,GPIO2_6,gpio2[6],,,,ehrpwm2A,,gpmc_a0,lcd_data0,R1,Allocated (Group: nxp_hdmi_bonelt_pins) P8_46,41,0x8a4/0a4,71,GPIO2_7,gpio2[7],,,,ehrpwm2B,,gpmc_a1,lcd_data1,R2,Allocated (Group: nxp_hdmi_bonelt_pins) P9_01,,,,GND,,,,,,,,,,Ground P9_02,,,,GND,,,,,,,,,,Ground P9_03,,,,DC_3.3V,,,,,,,,,, P9_04,,,,DC_3.3V,,,,,,,,,,250mA Max Current P9_05,,,,VDD_5V,,,,,,,,,, P9_06,,,,VDD_5V,,,,,,,,,,1A Max Current (only if DC jack powered) P9_07,,,,SYS_5V,,,,,,,,,,250mA Max Current P9_08,,,,SYS_5V,,,,,,,,,,250mA Max Current P9_09,,,,PWR_BUT,,,,,,,,,,Has a 5V Level (pulled up by TP65217C) P9_10,,,,SYS_RESETn,,,,,,,,RESET_OUT,A10, P9_11,28,0x870/070,30,UART4_RXD,gpio0[30],uart4_rxd_mux2,,mmc1_sdcd,rmii2_crs_dv,gpmc_csn4,mii2_crs,gpmc_wait0,T17,NB: GPIOs limit current to 4-6mA output and approx. 8mA on input P9_12,30,0x878/078,60,GPIO1_28,gpio1[28],mcasp0_aclkr_mux3,,gpmc_dir,mmc2_dat3,gpmc_csn6,mii2_col,gpmc_be1n,U18, P9_13,29,0x874/074,31,UART4_TXD,gpio0[31],uart4_txd_mux2,,mmc2_sdcd,rmii2_rxerr,gpmc_csn5,mii2_rxerr,gpmc_wpn,U17, P9_14,18,0x848/048,50,EHRPWM1A,gpio1[18],ehrpwm1A_mux1,,gpmc_a18,mmc2_dat1,rgmii2_td3,mii2_txd3,gpmc_a2,U14, P9_15,16,0x840/040,48,GPIO1_16,gpio1[16],ehrpwm1_tripzone_input,,gpmc_a16,mii2_txen,rmii2_tctl,gmii2_txen,gpmc_a0,R13, P9_16,19,0x84c/04c,51,EHRPWM1B,gpio1[19],ehrpwm1B_mux1,,gpmc_a19,mmc2_dat2,rgmii2_td2,mii2_txd2,gpmc_a3,T14, P9_17,87,0x95c/15c,5,I2C1_SCL,gpio0[5],,,,ehrpwm0_synci,I2C1_SCL,mmc2_sdwp,spi0_cs0,A16, P9_18,86,0x958/158,4,I2C1_SDA,gpio0[4],,,,ehrpwm0_tripzone,I2C1_SDA,mmc1_sdwp,spi0_d1,B16, P9_19,95,0x97c/17c,13,I2C2_SCL,gpio0[13],,,spi1_cs1,I2C2_SCL,dcan0_rx,timer5,uart1_rtsn,D17,Allocated (Group: pinmux_i2c2_pins) P9_20,94,0x978/178,12,I2C2_SDA,gpio0[12],,,spi1_cs0,I2C2_SDA,dcan0_tx,timer6,uart1_ctsn,D18,Allocated (Group: pinmux_i2c2_pins) P9_21,85,0x954/154,3,UART2_TXD,gpio0[3],EMU3_mux1,,,ehrpwm0B,I2C2_SCL,uart2_txd,spi0_d0,B17, P9_22,84,0x950/150,2,UART2_RXD,gpio0[2],EMU2_mux1,,,ehrpwm0A,I2C2_SDA,uart2_rxd,spi0_sclk,A17, P9_23,17,0x844/044,49,GPIO1_17,gpio1[17],ehrpwm0_synco,,gpmc_a17,mmc2_dat0,rgmii2_rxdv,gmii2_rxdv,gpmc_a1,V14, P9_24,97,0x984/184,15,UART1_TXD,gpio0[15],,,,I2C1_SCL,dcan1_rx,mmc2_sdwp,uart1_txd,D15, P9_25,107,0x9ac/1ac,117,GPIO3_21,gpio3[21],,,EMU4_mux2,mcasp1_axr1,mcasp0_axr3,eQEP0_strobe,mcasp0_ahclkx,A14,Allocated (Group: mcasp0_pins) P9_26,96,0x980/180,14,UART1_RXD,gpio0[14],,,,I2C1_SDA,dcan1_tx,mmc1_sdwp,uart1_rxd,D16, P9_27,105,0x9a4/1a4,115,GPIO3_19,gpio3[19],,,EMU2_mux2,mcasp1_fsx,mcasp0_axr3,eQEP0B_in,mcasp0_fsr,C13, P9_28,103,0x99c/19c,113,SPI1_CS0,gpio3[17],,,eCAP2_in_PWM2_out,spi1_cs0,mcasp0_axr2,ehrpwm0_synci,mcasp0_ahclkr,C12,Allocated (Group: mcasp0_pins) P9_29,101,0x994/194,111,SPI1_D0,gpio3[15],,,mmc1_sdcd_mux1,spi1_d0,,ehrpwm0B,mcasp0_fsx,B13,Allocated (Group: mcasp0_pins) P9_30,102,0x998/198,112,SPI1_D1,gpio3[16],,,mmc2_sdcd_mux1,spi1_d1,,ehrpwm0_tripzone,mcasp0_axr0,D12, P9_31,100,0x990/190,110,SPI1_SCLK,gpio3[14],,,mmc0_sdcd_mux1,spi1_sclk,,ehrpwm0A,mcasp0_aclkx,A13,Allocated (Group: mcasp0_pins) P9_32,,,,VADC,,,,,,,,,,Voltage Reference for ADC (NB:1.8V) P9_33,,,,AIN4,,,,,,,,,C8,NB: 1.8V tolerant P9_34,,,,AGND,,,,,,,,,,Ground for ADC P9_35,,,,AIN6,,,,,,,,,A8,NB: 1.8V tolerant P9_36,,,,AIN5,,,,,,,,,B8,NB: 1.8V tolerant P9_37,,,,AIN2,,,,,,,,,B7,NB: 1.8V tolerant P9_38,,,,AIN3,,,,,,,,,A7,NB: 1.8V tolerant P9_39,,,,AIN0,,,,,,,,,B6,NB: 1.8V tolerant P9_40,,,,AIN1,,,,,,,,,C7,NB: 1.8V tolerant P9_41A,109,0x9b4/1b4,20,CLKOUT2,gpio0[20],EMU3_mux0,,timer7_mux1,clkout2,tclkin,,xdma_event_intr1,D14,Both signals are connected to P21 of P11 P9_41B,,0x9a8/1a8,116,GPIO3_20,gpio3[20],,,emu3,Mcasp1_axr0,,eQEP0_index,mcasp0_axr1,D13,Both signals are connected to P21 of P11 P9_42A,89,0x964/164,7,GPIO0_7,gpio0[7],xdma_event_intr2,mmc0_sdwp,spi1_sclk,pr1_ecap0_ecap_capin_apwm_o,spi1_cs1,uart3_txd,eCAP0_in_PWM0_out,C18,Both signals are connected to P21 of P11 P9_42B,,0x9a0/1a0,114,GPIO3_18,gpio3[18],,,,Mcasp1_aclkx,Mcaspo_axr2,eQEP0A_in,Mcasp0_aclkr,B12,Both signals are connected to P21 of P11 P9_43,,,,GND,,,,,,,,,,See pg 50 of the SRM P9_44,,,,GND,,,,,,,,,,Ground P9_45,,,,GND,,,,,,,,,,Ground P9_46,,,,GND,,,,,,,,,,Ground EOD my %pinbyheadname = {}; my %pinbyname = {}; my %pinbyaddr = {}; my %pinbymode = {}; my %pinbycurrentmode = {}; foreach (split(/\n/, $data)) { if ($csv->parse($_)) { my @col = $csv->fields(); my $pin = {}; $pin->{headname} = $col[0] if $col[0]; $pin->{pin} = $col[1] if $col[1]; if ($col[2]) { $col[2] =~ s/(0x...).*/$1/; $pin->{addr} = $base + hex($col[2]); } $pin->{gpio} = $col[3] if $col[3]; $pin->{name} = $col[4] if $col[4]; $pin->{m7} = lc $col[5] if $col[5]; $pin->{m6} = lc $col[6] if $col[6]; $pin->{m5} = lc $col[7] if $col[7]; $pin->{m4} = lc $col[8] if $col[8]; $pin->{m3} = lc $col[9] if $col[9]; $pin->{m2} = lc $col[10] if $col[10]; $pin->{m1} = lc $col[11] if $col[11]; $pin->{m0} = lc $col[12] if $col[12]; $pin->{chippin} = $col[13] if $col[13]; $pin->{comment} = $col[14] if $col[14]; $pinbyheadname{$pin->{headname}} = $pin if $pin->{headname}; $pinbyname{$pin->{name}} = $pin if $pin->{name}; $pinbyaddr{$pin->{addr}} = $pin if $pin->{addr}; foreach my $mode ("m0","m1","m2","m3","m4","m5","m6","m7") { if ($pin->{$mode}) { my $modename = $pin->{$mode}; my @pinlist; my @pinlist = (); @pinlist = @{$pinbymode{$modename}} if (exists $pinbymode{$modename}); push (@pinlist, $pin); $pinbymode{$modename} = \@pinlist; } } } else { my $err = $csv->error_input; print "Failed to parse line: $err"; } } open(MUXSTATE, $muxfile) || die "$muxfile: $!"; while (<MUXSTATE>) { my ($pinix, $address, $muxstate) = /^pin (\d+) \(([a-z0-9]*)\) (\d+)/; $address = hex($address); $muxstate = hex($muxstate); if (exists $pinbyaddr{$address}) { my $pin = $pinbyaddr{$address}; $pin->{intpin} = $pinix; $pin->{muxstate} = $muxstate; $pin->{currentmode} = $pin->{sprintf("m%d", $pin->{muxstate}&7)}; $pinbycurrentmode{$pin->{currentmode}} = $pin; if ($pin->{currentmode} =~ /^gpio/) { $pin->{gpiofile} = sprintf("%s%d", $gpiobase, $pin->{gpio}); my $state = ""; if (-d $pin->{gpiofile}) { open (FD, sprintf("%s/direction", $pin->{gpiofile})) || die "direction: $!"; my $line = <FD>; close FD; ($state = $line) =~ s/\n//g; } else { if (($pin->{muxstate} & 0x20) == 0) { $state = "[out]"; } else { $state = "[in]"; } } if ($state =~ /in/) { if (($pin->{muxstate} & 0x8) == 0) { if (($pin->{muxstate} & 0x10) == 0) { $state = "$state [pulldown]"; } else { $state = "$state [pullup]"; } } } if (($pin->{muxstate} & 0x40) == 0) { $state = "$state [fast]"; } else { $state = "$state [slow]"; } $pin->{gpiostate} = $state; } } } close MUXSTATE; if ($ARGV[0] eq "list") { printf("%-7s %-6s %-12s %-20s %-20s\n", "HEADER", "GPIO", "NAME", "CURRENT-MODE", "GPIO-STATE"); foreach $_ (sort keys %pinbyheadname) { my $pin = $pinbyheadname{$_}; printf("%-7s %-6d %-12s %-20s %-20s\n", $pin->{headname}, $pin->{gpio}, $pin->{name}, $pin->{currentmode}, $pin->{gpiostate}); } } elsif ($ARGV[0] eq "find") { # print join(",", sort keys %pinbymode); my @list = (); push (@list, $pinbyheadname{uc $ARGV[1]}) if exists $pinbyheadname{uc $ARGV[1]}; push (@list, $pinbyname{uc $ARGV[1]}) if exists $pinbyname{uc $ARGV[1]}; push (@list, @{$pinbymode{lc $ARGV[1]}}) if exists $pinbymode{lc $ARGV[1]}; my %dup = (); printf("%-7s %-6s %-12s %-20s %s\n", "HEADER", "GPIO", "NAME", "CURRENT-MODE", "OTHER-MODES"); foreach my $pin (@list) { unless (exists $dup{$pin->{headname}}) { printf("%-7s %-6d %-12s %-20s", $pin->{headname}, $pin->{gpio}, $pin->{name}, $pin->{currentmode}); foreach my $mode ("m0","m1","m2","m3","m4","m5","m6","m7") { if (exists $pin->{$mode} && $pin->{currentmode} ne $pin->{$mode}) { printf(" %s", $pin->{$mode}); } } printf("\n"); $dup{$pin->{headname}} = $pin; } } if ($#list < 0) { printf("No such pin: %s\n", $ARGV[1]); } } elsif ($ARGV[0] eq "setgpio") { my $pin = $pinbyheadname{uc $ARGV[1]} ; if (!defined($pin)) { $pin = $pinbycurrentmode{lc $ARGV[1]}; } if (!defined($pin)) { printf("No such pin: %s\n", $ARGV[1]); } elsif ($pin->{currentmode} !~ /^gpio/) { printf("Not a GPIO pin: %s mode is %s\n", $ARGV[1], $pin->{currentmode}); } else { my $pinnum = $pin->{gpio}; my $pinfile = $pin->{gpiofile}; if ($ARGV[2] eq "in") { if (!-f $pinfile) { open (FD, ">$ctrlfile/export") || die "$ctrlfile/export: $1"; print FD "$pinnum\n"; close FD; } open (FD, ">$pinfile/direction") || die "$pinfile/direction: $!"; print FD "in\n"; close FD; } elsif ($ARGV[2] eq "out") { if (!-f $pinfile) { open (FD, ">$ctrlfile/export") || die "$ctrlfile/export: $!"; print FD "$pinnum\n"; close FD; } open (FD, ">$pinfile/direction") || die "$pinfile/direction: $!"; print FD "out\n"; close FD; if ($ARGV[3] eq "0" || $ARGV[3] eq "1") { open (FD, ">$pinfile/value") || die "$pinfile/direction: $!"; print FD "$ARGV[2]\n"; close FD; } } elsif ($ARGV[2] eq "disable") { if (!$pinfile) { open (FD, ">$ctrlfile/unexport") || die "$ctrlfile/unexport: $!"; print FD "$pinnum\n"; close FD; } } } } else { print<<EOF Usage: bbpins.pl list list the state of the pins, for example: P9_26 14 uart1_rxd P9_27 115 gpio3[19] [in] [pulldown] [fast] This shows the pin positions, the GPIO number, the name of the current pin mode, and for GPIO pins the GPIO state - input (with pullup/pulldown), output, and the slew mode (fast or slow). If the value is in square brackets, ie [input], it is derived from the pinmux file. Otherwise it is read directly from the enabled GPIO directory bbpins.pl find <pinname> find the pins with the specified name, eg "find uart5_txd" bbpins.pl gpio <pinname> [in|out|disable] [1|0]* set the specified pin to input, output or disabled. If output, the second argument can be 1 or 0 to set the state of the pin EOF }
Perl is a bit rusty, sorry. Here's an excerpt of sample output:
# bbpins.pl list HEADER GPIO NAME CURRENT-MODE GPIO-STATE P8_25 1 GPIO1_0 mmc1_dat0 P8_26 61 GPIO1_29 gpio1[29] [in] [pullup] [fast] P8_27 86 GPIO2_22 gpio2[22] [in] [pulldown] [fast] P8_28 88 GPIO2_24 gpio2[24] [in] [pulldown] [fast]
# bbpins.pl find uart5_rxd HEADER GPIO NAME CURRENT-MODE OTHER-MODES P8_38 79 UART5_RXD uart5_rxd lcd_data9 gpmc_a13 ehrpwm0_synco mcasp0_fsx uart2_rtsn gpio2[15] P8_31 10 UART5_CTSN eqep1_index lcd_data14 gpmc_a18 mcasp0_axr1 uart5_rxd uart5_ctsn gpio0[10]
You can download it bbpins.pl. With this you can list the pins, including the current mux state (which includes the state of the pullups/pulldowns), you can find a pin by name or function, and you can turn a pin on or off by name or function.
Perhaps it will be a starting point for some better tools to manage this? I hope so: if I want to change the pullup/pulldown values it looks like I have to do this by writing, compiling and loading a Device Tree Overlay... ugh.