Step04 – GPIO1

Pin Muxes

The pins on the Beaglebone processor which are available for general IO also have several other functions that they can be tied too. For example, some pins can be configured as UART Tx or Rx, or PWM outputs, etc. The mux settings is chosen at runtime and can be set through the sysfs.

On the beaglebone the pin mux settings are available at:

[code]/sys/kernel/debug/omap_mux/uart1_txd[/code]

Listing this directory, we get a large list of mux settings. Each of these mux settings represent a pin. For some reason, the default mux name (MODE 0) is used for these files instead of their generic name (i.e. either a ball reference, or else their GPIO number). So it can be quite awkward to work out what file you’re after in this directory if you’re just after setting a GPIO line to GPIO mode.

NOTE: If a GPIO line does not have its pin mux setting to GPIO mode (MODE 7), then the pin will not respond to anything we do later in trying to manipulate the pin. The pin mux mode is very important and should be set to GPIO mode for every pin we wish to have under general IO control.

[code]root@beaglebone:/sys/kernel/debug/omap_mux# ls
ain0 gpmc_ad2 lcd_data3 mii1_txd2
ain1 gpmc_ad3 lcd_data4 mii1_txd3
ain2 gpmc_ad4 lcd_data5 mii1_txen
ain3 gpmc_ad5 lcd_data6 mmc0_clk
ain4 gpmc_ad6 lcd_data7 mmc0_cmd
ain5 gpmc_ad7 lcd_data8 mmc0_dat0
ain6 gpmc_ad8 lcd_data9 mmc0_dat1
ain7 gpmc_ad9 lcd_hsync mmc0_dat2
board gpmc_advn_ale lcd_pclk mmc0_dat3
ecap0_in_pwm0_out gpmc_ben0_cle lcd_vsync rmii1_refclk
emu0 gpmc_ben1 mcasp0_aclkr spi0_cs0
emu1 gpmc_clk mcasp0_aclkx spi0_cs1
gpmc_a0 gpmc_csn0 mcasp0_ahclkr spi0_d0
gpmc_a1 gpmc_csn1 mcasp0_ahclkx spi0_d1
gpmc_a10 gpmc_csn2 mcasp0_axr0 spi0_sclk
gpmc_a11 gpmc_csn3 mcasp0_axr1 uart0_ctsn
gpmc_a2 gpmc_oen_ren mcasp0_fsr uart0_rtsn
gpmc_a3 gpmc_wait0 mcasp0_fsx uart0_rxd
gpmc_a4 gpmc_wen mdio_clk uart0_txd
gpmc_a5 gpmc_wpn mdio_data uart1_ctsn
gpmc_a6 i2c0_scl mii1_col uart1_rtsn
gpmc_a7 i2c0_sda mii1_crs uart1_rxd
gpmc_a8 lcd_ac_bias_en mii1_rxclk uart1_txd
gpmc_a9 lcd_data0 mii1_rxd0 usb0_drvvbus
gpmc_ad0 lcd_data1 mii1_rxd1 usb1_drvvbus
gpmc_ad1 lcd_data10 mii1_rxd2 vrefn
gpmc_ad10 lcd_data11 mii1_rxd3 vrefp
gpmc_ad11 lcd_data12 mii1_rxdv xdma_event_intr0
gpmc_ad12 lcd_data13 mii1_rxerr xdma_event_intr1
gpmc_ad13 lcd_data14 mii1_txclk
gpmc_ad14 lcd_data15 mii1_txd0
gpmc_ad15 lcd_data2 mii1_txd1[/code]

The processor on the BeagleBone is a Texas Instrument AM3359 ( http://www.ti.com/product/am3359 ). Although we can look at the Beaglebone user manual to get some of the GPIO names listed above, they’re not all present. When you look in the manual ( http://www.ti.com/litv/pdf/spruh73f ) it’s more obvious why, there are a lot of pins and a lot of MUX options!

NOTE: The pin mux information is only in the shorter datasheet actually as it details the complete processor, not just the core: ( http://www.ti.com/lit/ds/symlink/am3359.pdf )

But, we need to know the mux options so that we know what file to use to setup our GPIO lines.

What I’m interested in is GPIO1_0 to GPIO1_31. My project requires most of these pins. Looking through the 20-odd pages of the pin mux table, I conclude the following:

[code]GPIO1_0 = gpmc_ad0
GPIO1_1 = gpmc_ad1
GPIO1_2 = gpmc_ad2
GPIO1_3 = gpmc_ad3
GPIO1_4 = gpmc_ad4
GPIO1_5 = gpmc_ad5
GPIO1_6 = gpmc_ad6
GPIO1_7 = gpmc_ad7
GPIO1_8 = uart0_ctsn
GPIO1_9 = uart0_rtsn
GPIO1_10 = uart0_rxd
GPIO1_11 = uart0_txd
GPIO1_12 = gpmc_ad12
GPIO1_13 = gpmc_ad13
GPIO1_14 = gpmc_ad14
GPIO1_15 = gpmc_ad15
GPIO1_16 = gpmc_a0
GPIO1_17 = gpmc_a1
GPIO1_18 = gpmc_a2
GPIO1_19 = gpmc_a3
GPIO1_20 = gpmc_a4
GPIO1_21 = gpmc_a5
GPIO1_22 = gpmc_a6
GPIO1_23 = gpmc_a7
GPIO1_24 = gpmc_a8
GPIO1_25 = gpmc_a9
GPIO1_26 = gpmc_a10
GPIO1_27 = gpmc_a11
GPIO1_28 = gpmc_be1n
GPIO1_29 = gpmc_csn0
GPIO1_30 = gpmc_csn1
GPIO1_31 = gpmc_csn2[/code]

It would be good to symlink those files tbh so that we don’t have to try and remember this mapping!

You can also cat these files to see what options they have, and what their current setting is:

[code]root@beaglebone:/sys/kernel/debug/omap_mux# cat gpmc_a0
name: gpmc_a0.gpio1_16 (0x44e10840/0x840 = 0x0027), b NA, t NA
mode: OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE7
signals: gpmc_a0 | gmii2_txen | rgmii2_tctl | rmii2_txen | gpmc_a16 | pr1_mii_mt1_clk | ehrpwm1_tripzone_input | gpio1_16

root@beaglebone:/sys/kernel/debug/omap_mux# cat gpmc_a1
name: gpmc_a1.gpio1_17 (0x44e10844/0x844 = 0x0027), b NA, t NA
mode: OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE7
signals: gpmc_a1 | gmii2_rxdv | rgmii2_rctl | mmc2_dat0 | gpmc_a17 | pr1_mii1_txd3 | ehrpwm0_synco | gpio1_17
root@beaglebone:/sys/kernel/debug/omap_mux#[/code]

One of the pins I want to use is GPIO1_0 which is gmpc_ad0. NOTE: You can easily grep the directory to find out which file relates to the GPIO pin you’re interested in. For example, you can find where gpio1_0 is like so:

[code]grep gpio1_0 -r .[/code]

which results in the following output:

[code]./gpmc_ad0:signals: gpmc_ad0 | mmc1_dat0 | NA | NA | NA | NA | NA | gpio1_0[/code]

I check to see what this pin is set to and find that its set to MODE0 and is an input. I need to change it to MODE7 (Which is the GPIO mode for all GPIO pins):

[code]root@beaglebone:/sys/kernel/debug/omap_mux# cat gpmc_ad0
name: gpmc_ad0.gpmc_ad0 (0x44e10800/0x800 = 0x0030), b NA, t NA
mode: OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0
signals: gpmc_ad0 | mmc1_dat0 | NA | NA | NA | NA | NA | gpio1_0[/code]

We can change the mode of this pin to GPIO by simply writing the hex value 0x07 to it to set it into mode 7:

[code]root@beaglebone:/sys/kernel/debug/omap_mux# echo 07 > gpmc_ad0
root@beaglebone:/sys/kernel/debug/omap_mux# cat gpmc_ad0
name: gpmc_ad0.gpio1_0 (0x44e10800/0x800 = 0x0007), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_ad0 | mmc1_dat0 | NA | NA | NA | NA | NA | gpio1_0[/code]

That’s better. Of course this can be done in software too, but it is not part of the standard GPIO sysfs driver. The GPIO sysfs driver assumes that the pins are muxed correctly.

There’s a bit more to the mode that than though. There are some other bits in the mode value that set various options:

Bit 1 0
5 Receive Enable Receive Disable
4 Pullup Pulldown
3 Pullup/down Disabled Pullup/down Enabled
2, 1, 0 Mode

When writing to the file, the value must be in hex. So if you want to enable a pullup and set the line as a GPIO line (mode 7), the binary would be 0b10111. Which in turn is decimal 23, and hex 17. You need to use the hex notation in the echo command: “echo 17 > gpmc_ad0”, ec.

Get some IO

Now, let’s get controlling IO lines!

Firstly, using the system filesystem driver from the command line, we can control a pin. I will carry on using GPIO1_0 which we just setup to be mode 7 (GPIO). You’ll need an oscilloscope or multimeter on this pin in order to see the difference in the output.

[code]root@beaglebone:/sys/class/gpio# ls
export gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport[/code]

We need to navigate to the system GPIO class. Here we get a list of files for the GPIO driver. A pin cannot be controlled until it has been exported. If your application requires control of a pin, it should export it in order to get access to the pin. If export is unsuccessful some other resource is already using that pin.

In order to export a pin on BeagleBone we write the pin number to the GPIO export file. The pin number comes from its GPIO designation, not the IC pin number. Each IO port has 32-bits, and the ports are concatenated, so the first number of a GPIO designation (the port number) is multiplied by 32, and then the bit number of the port is added to get the GPIO pin number.

For example, to export GPIO1_0 we write (1*32) +  0 = 32 to the export file:

[code]root@beaglebone:/sys/class/gpio# echo 32 > export

root@beaglebone:/sys/class/gpio# ls
export gpio32 gpiochip0 gpiochip32 gpiochip64 gpiochip96 unexport[/code]

Once we’ve exported the pin, we’re ready to configure it and use it. As you can see above, when we look at the filesystem after the pin has been exported, we see there is a new file (directory!) for GPIO1_0 (32). So go ahead and have a look inside the the pins directory to find yet more files relating the GPIO1_0 pin:

[code]root@beaglebone:/sys/class/gpio# cd gpio32/

root@beaglebone:/sys/class/gpio/gpio32# ls
active_low direction edge power subsystem uevent value[/code]

The direction and value files are the most important for us during standard GPIO use where we just want to set a direction and value (Obviously!)

The direction and value files are extremely easy to use. We can set direction to either in, or out, and we can set the value file to either 0 (for logic low) or 1 (for logic high).

For example, to set the GPIO to an output with logic high:

[code]root@beaglebone:/sys/class/gpio/gpio32# echo out > direction

root@beaglebone:/sys/class/gpio/gpio32# echo 1 > value[/code]

The code for doing this will come soon. We’ll just develop a quick file which will write to these files to control IO lines from C. There is some more to learn for special functions (modes other than 0x07) for GPIO lines when we want to control peripherals like I2C and UART.

Leave a Reply