Home‎ > ‎Sergey's Blog‎ > ‎

Intel Galileo - Programming GPIO From Linux

posted Oct 28, 2013, 11:59 PM by Sergey Kiselev   [ updated Jan 15, 2014, 12:14 PM ]
Most of GPIO capabilities of Galileo board are exposed through Linux Sysfs interface, and can be controlled using file based I/O. I will show how to use some of these capabilities using simple shell commands. Of course instead of shell you can implement I/O using file manipulations from your program written using your favorite programming language.

Digital GPIO - Sysfs Interface

GPIO Information

The following command gives information about GPIO in the system and shows if an IO port was allocated to a module or Sysfs (user).

root@clanton:~# cat /sys/kernel/debug/gpio

GPIOs 0-1, platform/sch_gpio.2398, sch_gpio_core:


GPIOs 2-7, platform/sch_gpio.2398, sch_gpio_resume:


GPIOs 8-15, intel_cln_gip_gpio:

gpio-8   (SPI_CS              ) out hi

gpio-10  (SPI_CS              ) out hi

gpio-13  (cy8c9540a-int       ) in  hi


GPIOs 16-55, cy8c9540a, can sleep:

As you can see from the output all the GPIOs of Galileo board is divided into 4 chunks:
  1. GPIOs 0-1 - Intel Quark X1000 - GPIO[9:8] pins. These are GPIO pins on Legacy I/O bridge. They are powered and active in S0 state only.
  2. GPIOs 2-7 - Intel Quark X1000 - GPIO_SUS[5:0] pins. These are GPIO pins on Legacy I/O bridge. They are powered and active in S3 (suspend) and S0 states.
  3. GPIOs 8-15 - Intel Quark X1000 - GPIO[7:0] pins. These are GPIO pins on GPIO controller. They are powered and active in S0 state only.
  4. GPIOs 16-55 - Cypress CY8C9540A I/O Expander

Exporting a GPIO Port to Sysfs

To make GPIO port controllable from sysfs you'll need to export it. This is done by writing GPIO port number to /sys/class/gpio/export:

root@clanton:~# echo -n "27" > /sys/class/gpio/export

When this operation completes successfully a directory corresponding to the GPIO port number will appear in sysfs. In this case /sys/class/gpio/gpio27. Once you finished working with I/O you should un-export it by writing the GPIO port number to /sys/class/gpio/unexport.

Setting GPIO Port Direction

I/O direction is set by writing "in" (for input) or "out" (for output) to /sys/class/gpio/gpioXX/direction file.

root@clanton:~# echo -n "out" > /sys/class/gpio/gpio27/direction

Setting GPIO Port Drive Configuration

When configured for output GPIO ports that are connected to CY8C9520A can be configured to one of the following drive modes:

  • Resistive high, strong low (drive = pullup)
    • This is the default, but it not suitable for driving devices that source significant current, for example for driving an LED connected between GPIO port and GND (it will work though if the LED is connected between GPIO and 5V or 3.3V rails)
  • Resistive low, strong high (drive = pulldown)
  • Strong low and high (drive = strong)
    • This mode is appropriate for most applications.
  • High Z state (drive = hiz)
  • (CY8C9520A also supports open drain and open source drive modes, but it is not currently exposed through SysFS)

The drive mode is set by writing the mode string ("pullup", "pulldown", "strong", or "hiz") to /sys/class/gpio/gpioXX/drive.

root@clanton:~# echo -n "strong" > /sys/class/gpio/gpio27/drive

Reading and Writing GPIO Port

When GPIO port is configured for input the input value (0 or 1) can be read from /sys/class/gpio/gpioXX/value file.
root@clanton:~# cat /sys/class/gpio/gpio27/value
0
When GPIO port is configured for output the output value can be written to the same file:
root@clanton:~# echo -n "1" > /sys/class/gpio/gpio27/value
root@clanton:~# echo -n "0" > /sys/class/gpio/gpio27/value

Pulse-Width Modulation

Pulse width modulation (PWM) is a technique of simulating an analog output signal using a digital signal switched on and off repeatedly for certain intervals. It is widely used to regulate intensity of LEDs, to control speed of DC motors, and so on.

Checking the number of PWM Channels

root@clanton:~# cat /sys/class/pwm/pwmchip0/npwm
8

In Galileo all PWM outputs are implemented using Cypress CY8C9540A. It supports 8 PWM channels, but only 6 are used in Galileo. They are mapped as follows:

  Arduino Digital Pin NumberPWM Channel Number
 3 3
 5 5
 6 6
 9 1
 10 7
 11 4

Exporting a PWM Channel to Sysfs

root@clanton:~# echo -n "3" > /sys/class/pwm/pwmchip0/export
This is very similar to exporting GPIO above. Same as with GPIO once a port is exported a corresponding directory with control files will appear in Sysfs: /sys/class/pwm/pwmchip0/pwm3/enable in this case. And just as with GPIO when PWM port is no longer needed it should be un-exported by writing the port number to /sys/class/pwmchip0/unexport.

Enabling PWM and Setting PWM Parameters

To enable a PWM on a port write "1" to a corresponding enable file. To disable a port write "0".
root@clanton:~# echo -n "1" > /sys/class/pwm/pwmchip0/pwm3/enable

To set a PWM period write period in nanoseconds to period file. In example below it is set to 1000000 nanoseconds or 1 millisecond:
root@clanton:~# echo -n "1000000" > /sys/class/pwm/pwmchip0/pwm3/period

To set a PWM duty cycle write its length in nanoseconds to duty_cycle file. In example below we set duty cycle to 50% (500000/1000000*100%):
root@clanton:~# echo -n "500000" > /sys/class/pwm/pwmchip0/pwm3/duty_cycle

Analog Input

Analog inputs in Galileo implemented using Analog Devices AD7298 ADC IC. This IC has 8 channels, but only 6 channels are connected in Galileo. The resolution of each channel is 12 bit. So resulting values will be in range 0 - 4095. 0 - input voltage 0V (ground), 4095 - input equals 5V (power supply).

In Sysfs analog inputs can be read from /sys/bus/iio/devices/iio:device0/in_voltageX_raw files. Since analog inputs are multiplexed with GPIO and I2C (in case of A4 and A5) it is needed to enable analog input first. Multiplexers are controlled using regular GPIO pins. Example below shows how to do that for A0. Refer to the table below to find out corresponding multiplexer ports for other analog ports.

root@clanton:~# echo -n "37" > /sys/class/gpio/export
root@clanton:~# echo -n "out" > /sys/class/gpio/gpio37/direction
root@clanton:~# echo -n "0" > /sys/class/gpio/gpio37/value
First echo command exports GPIO port 37 which is used to control A0 multiplexer. Second echo command configures that GPIO for output. Third echo command connects A0 to ADC chip.

Once analog port is connected, its value can be read from Sysfs:
root@clanton:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
2593

Other Functionality

Fast I/O

In addition to regular I/O through Sysfs Galileo supports fast I/O on digital pins 2 and 3 which can be connected using multiplexer directly to Intel Quark X1000. The fast I/O is done using /dev/uio0 device. I haven't tested this functionality yet and will report it later.

SPI I/O

Digital pins 10 - 13 can be connected to Intel Quark X1000's SPI1 interface. I am not sure yet if this interface is exposed to userspace. I need to investigate it.

I2C I/O

Pins A4 and A5 and also SDA and SCL pins can be connected to Intel Quark X1000's I2C interface. Again I haven't tried this functionality yet.

GPIO Mapping in Galileo

This is probably the most important (and the most confusing) part of this post. It took me a while to parse the schematic and the supplied Arduino code to come up with this diagram and table. Hopefully it will tell you exactly what to do if you want to use some pins for certain function.

GPIO Pins Connection Diagram

Labels on the left size indicate names of ports in SysFS GPIO and PWM (where applicable) interfaces, or Intel Quark X1000 connections: ttyS0 for the serial port signals; SPI1 for SPI interface signals, and I2C for I2C signals. ADC inputs are named vin0 to vin7 and correspond to /sys/bus/iio/devices/iio:device0/in_voltage0_raw - /sys/bus/iio/devices/iio:device0/in_voltage7_raw respectively.

Labels on the right side indicate names of Arduino shield ports.

The trapezoid shaped things are bidirectional multiplexers (or switches). They are controlled by the signal coming on the top (selector input). When the selector value is 0 it connects 0 pin on the left side of multiplexer to the pin on the right side of multiplexer; when the selector value is 1 it connects pin 1 on the left side to the pin on the right side. To give an example if you want to connect Arduino A1 pin to ADC vin1, you'll need to set gpio36 to "0".

(Click on the diagram to zoom in)

GPIO Pins Assignment

Quark X1000

Sysfs GPIO #

Signal Name / Arduino Port #

Function and Comments

GPIO_SUS0

gpio2

INT_N_S3

Don’t touch, or bad things will happen :-)

GPIO_SUS1

gpio3

GP LED

LED between Cypress CY8C9540A and RTC battery header

GPIO_SUS2

gpio4

LVL_OE

TXS0108E level shifter output enable.

GPIO_SUS3

gpio5

GPIO_SUS3_PCIE_RESET_N

Reset to Mini PCI-E slot

GPIO_SUS4

gpio6

GPIO_SUS4_W_DISABLE_N

Wireless disable (RF Kill to PCI-E Slot)

GPIO_SUS5

gpio7

A0_N

Jumper J2 (Cypress CY8C9540A I2C address select)

GPIO0

gpio8

SPI0_CS_N

Select SPI for AD7298

GPIO1

gpio9

Not Connected


GPIO2

gpio10

SPI1_CS_N

Routed to IO10 if selected by IO10_MUX (libgpio42=0)

GPIO3

gpio11

Not Connected


GPIO4

gpio12

XRES

Reset to Cypress CY8C9540A

GPIO5

gpio13

INT_N_S0

Don’t touch too :-)

GPIO6

gpio14

IO2

Selected by IO2_MUX (gpio31=0)

GPIO7

gpio15

IO3

Selected by IO3_MUX (gpio30=0)

GPIO8

gpio0

GLN_IO2_PU_EN

Enable pullup on IO2/GPIO6

GPIO9

gpio1

GLN_IO3_PU_EN

Enable pullup on IO3/GPIO7

CY8C9540A

Sysfs GPIO #Signal Name / Arduino Port #Function and Comments

GPORT0_BIT0

gpio16

IO10

Selected by IO10_MUX (GPORT3_BIT6, gpio42)

Also controlled by pwm7

GPORT0_BIT1

gpio17

IO5

Also controlled by pwm5

GPORT0_BIT2

gpio18

IO3

Selected by IO3_MUX (gpio30=1)

Also controlled by pwm3

GPORT0_BIT3

gpio19

IO9

Also controlled by pwm1

GPORT0_BIT4

gpio20

A5_MUX

Selects A5 pin routing:

0 = AD7298 (VIN5)

1 = Cypress CY8C9540A (GPORT4_BIT5, gpio49)

GPORT0_BIT5

gpio21

A4_MUX

Selects A4 pin routing:

0 = AD7298 (VIN4)

1 = Cypress CY8C9540A (GPORT4_BIT4, gpio48)

GPORT0_BIT6

gpio22

A3_MUX

Selects A3 pin routing:

0 = AD7298 (VIN3)

1 = Cypress CY8C9540A (GPORT4_BIT3, gpio47)

GPORT0_BIT7

gpio23

A2_MUX

Selects A2 pin routing:

0 = AD7298 (VIN2)

1 = Cypress CY8C9540A (GPORT4_BIT2, gpio46)

GPORT1_BIT0

gpio24

IO6

Also controlled by pwm6

GPORT1_BIT1

gpio25

IO11

Selected by IO11_MUX (GPORT3_BIT7, gpio43)

Also controlled by pwm4

GPORT1_BIT2

gpio26

IO8


GPORT1_BIT3

gpio27

IO7


GPORT1_BIT4

gpio28

IO4


GPORT1_BIT5

gpio29

I2C_MUX

Selects between GPIO and I2C on pins A4 and A5:

0= Quark I2C

1 = GPIO (Cypress CY8C9540A, AD7298)

GPORT1_BIT6

gpio30

IO3_MUX

Selects IO3 pin routing:
0 = Quark (GPIO7, gpio15)

1 = Cypress CY8C9540A (GPORT9_BIT2, gpio18)

GPORT1_BIT7

gpio31

IO2_MUX

Selects IO2 pin routing:

0 = Quark (GPIO6, gpio14)

1 = Cypress CY8C9540A (GPORT2_BIT0, gpio32)

GPORT2_BIT0

gpio32

IO2

Selected by IO_MUX (gpio31=1)

GPORT2_BIT1

gpio33

Not Connected


GPORT2_BIT2

gpio34

Not Connected


GPORT2_BIT3

gpio35

Not Connected


GPORT3_BIT0

gpio36

A1_MUX

Select A1 pin routing:

0 = AD7298 (VIN1)

1 = Cypress CY8C9540A (GPORT4_BIT1, gpio45)

GPORT3_BIT1

gpio37

A0_MUX

Select A0 pin routing:

0 = AD7298 (VIN0)

1 = Cypress CY8C9540A (GPORT4_BIT0, gpio44)

GPORT3_BIT2

gpio38

IO12

Selected by IO12_MUX (gpio54=1)

GPORT3_BIT3

gpio39

IO13

Selected by IO13_MUX (gpio55=1)

GPORT3_BIT4

gpio40

IO0_MUX

Select IO0 pin routing:

0 = Quark UART0 RXD (/dev/ttyS0)

1 = Cypress CY8C9540A (GPORT4_BIT6, gpio50)

GPORT3_BIT5

gpio41

IO1_MUX

Select IO1 pin routing:

0 = Quark UART0 TXD (/dev/ttyS0)

1 = Cypress (GPORT4_BIT7, gpio51)

GPORT3_BIT6

gpio42

IO10_MUX

Select IO10 pin routing:

0 = Quark SPI1_CS

1 = Cypress (GPORT0_BIT0, gpio16)

GPORT3_BIT7

gpio43

IO11_MUX

Select IO11 pin routing:

0 = Quark SPI1_MOSI

1 = Cypress (GPORT1_BIT1, gpio25)

GPORT4_BIT0

gpio44

A0

Selected by A0_MUX (gpio37=1)

GPORT4_BIT1

gpio45

A1

Selected by A1_MUX (gpio36=1)

GPORT4_BIT2

gpio46

A2

Selected by A2_MUX (gpio23=1)

GPORT4_BIT3

gpio47

A3

Selected by A3_MUX (gpio22=1)

GPORT4_BIT4

gpio48

A4

Selected by A4_MUX (gpio21=1) and I2C_MUX (gpio29=1)

GPORT4_BIT5

gpio49

A5

Selected by A5_MUX (gpio20=1) and I2C_MUX (gpio29=1)

GPORT4_BIT6

gpio50

IO0

Selected by IO0_MUX (gpio40=1)

GPORT4_BIT7

gpio51

IO1

Selected by IO1_MUX (gpio41=1)

GPORT5_BIT0

gpio52

RESET (Input)

Connected to shield and to the RESET button.

GPORT5_BIT1

gpio53

RESET (Output)


GPORT5_BIT2

gpio54

IO12_MUX

Selects IO12 pin routing:

0 = Quark SPI_MISO

1 = Cypress (PORT3_BIT2, gpio38)

GPORT5_BIT3

gpio55

IO13_MUX

Selects IO13 pin routing:

0 = Quark SPI_SCK
1 = Cypress (PORT3_BIT3, gpio39)

AD7298

Sysfs GPIO #Signal Name / Arduino Port #Function and Comments

VIN1

in_voltage0_raw

A0

Selected by A0_MUX (gpio37=0)

VIN2

in_voltage1_raw

A1

Selected by A1_MUX (gpio36=0)

VIN3

in_voltage2_raw

A2

Selected by A2_MUX (gpio23=0)

VIN3

in_voltage3_raw

A3

Selected by A3_MUX (gpio22=0)

VIN4

in_voltage4_raw

A4

Selected by A4_MUX (gpio21=0) and I2C_MUX (gpio29=1)

VIN5

in_voltage5_raw

A5

Selected by A5_MUX (gpio20=0) and I2C_MUX (gpio29=1)

VIN6

in_voltage6_raw

Not Connected


VIN7

in_voltage7_raw

Not Connected





Comments