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