Open RF Prototyping

Using GPIO on the Red Pitaya Board

Configuring the GPIO Hardware

Pavel Demin's red-pitaya-notes configuration and build infrastructure is used to build the Zynq FPGA bitstream and associated Linux kernel. The required GPIO pin mappings are configured as part of this.

In red-pitaya-notes/cfg/ports.tcl the GPIO ports exp_p_tri_io and exp_n_tri_io are defined as:

create_bd_port -dir IO -from 7 -to 0 exp_p_tri_io
create_bd_port -dir IO -from 7 -to 0 exp_n_tri_io

The package pin mappings are in red-pitaya-notes/cfg/ports.xdc:

set_property PACKAGE_PIN G17 [get_ports {exp_p_tri_io[0]}]
set_property PACKAGE_PIN G18 [get_ports {exp_n_tri_io[0]}]
set_property PACKAGE_PIN H16 [get_ports {exp_p_tri_io[1]}]
set_property PACKAGE_PIN H17 [get_ports {exp_n_tri_io[1]}]
set_property PACKAGE_PIN J18 [get_ports {exp_p_tri_io[2]}]
set_property PACKAGE_PIN H18 [get_ports {exp_n_tri_io[2]}]
set_property PACKAGE_PIN K17 [get_ports {exp_p_tri_io[3]}]
set_property PACKAGE_PIN K18 [get_ports {exp_n_tri_io[3]}]
set_property PACKAGE_PIN L14 [get_ports {exp_p_tri_io[4]}]
set_property PACKAGE_PIN L15 [get_ports {exp_n_tri_io[4]}]
set_property PACKAGE_PIN L16 [get_ports {exp_p_tri_io[5]}]
set_property PACKAGE_PIN L17 [get_ports {exp_n_tri_io[5]}]
set_property PACKAGE_PIN K16 [get_ports {exp_p_tri_io[6]}]
set_property PACKAGE_PIN J16 [get_ports {exp_n_tri_io[6]}]
set_property PACKAGE_PIN M14 [get_ports {exp_p_tri_io[7]}]
set_property PACKAGE_PIN M15 [get_ports {exp_n_tri_io[7]}]

The GPIO port package pins are routed to the E1 expansion connector on the Red Pitaya board. Table 1 shows the mappings from the GPIO signal lines to the E1 pins.

Table 1: Red Pitaya board GPIO signal lines

Port

GPIO Signal

E1 Pin

exp_p_tri_io[0]

DIO0_P

3

exp_n_tri_io[0]

DIO0_N

4

exp_p_tri_io[1]

DIO1_P

5

exp_n_tri_io[1]

DIO1_N

6

exp_p_tri_io[2]

DIO2_P

7

exp_n_tri_io[2]

DIO2_N

8

exp_p_tri_io[3]

DIO3_P

9

exp_n_tri_io[3]

DIO3_N

10

exp_p_tri_io[4]

DIO4_P

11

exp_n_tri_io[4]

DIO4_N

12

exp_p_tri_io[5]

DIO5_P

13

exp_n_tri_io[5]

DIO5_N

14

exp_p_tri_io[6]

DIO6_P

15

exp_n_tri_io[6]

DIO6_N

16

exp_p_tri_io[7]

DIO7_P

17

exp_n_tri_io[7]

DIO7_N

18

For this example, we make use of the 'negative' half of the GPIO outputs. The associated input/output ports are first deleted and then an interface port containing these lines is created:

delete_bd_objs [get_bd_ports exp_n_tri_io]
create_bd_intf_port -mode Master -vlnv xilinx.com:interface:gpio_rtl:1.0 exp_n

Now an instance of axi_gpio is created in the Vivado block design using the above interface:

cell xilinx.com:ip:axi_gpio axi_gpio_0 {
    C_GPIO_WIDTH 8
} {
    GPIO exp_n
}

Vivado will generate the following device tree entry for the GPIO hardware:

axi_gpio_0: gpio@41200000 {
        #gpio-cells = <3>;
        clock-names = "s_axi_aclk";
        clocks = <&misc_clk_0>;
        compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
        gpio-controller ;
        reg = <0x41200000 0x10000>;
        xlnx,all-inputs = <0x0>;
        xlnx,all-inputs-2 = <0x0>;
        xlnx,all-outputs = <0x0>;
        xlnx,all-outputs-2 = <0x0>;
        xlnx,dout-default = <0x00000000>;
        xlnx,dout-default-2 = <0x00000000>;
        xlnx,gpio-width = <0x8>;
        xlnx,gpio2-width = <0x20>;
        xlnx,interrupt-present = <0x0>;
        xlnx,is-dual = <0x0>;
        xlnx,tri-default = <0xFFFFFFFF>;
        xlnx,tri-default-2 = <0xFFFFFFFF>;
};

Note that this uses the Xilinx GPIO driver (drivers/gpio/gpio-xilinx.d) and the following kernel config. options are set in arch/arm/configs/xilinx_zynq_defconfig:

CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_XILINX=y
CONFIG_GPIO_ZYNQ=y

This builds the GPIO kernel driver as a module which loads at boot time. The GPIO module creates the /dev/gpiochip1 device.

The Running System

The GPIO device is available as /dev/gpiochip1. The ownership and permissions should be changed appropriately in order to allow access from the application.

chgrp dyadic /dev/gpiochip1
chmod g+rw /dev/gpiochip1
# ls -l /dev/gpiochip1
crw-rw---- 1 root dyadic 254, 1 Oct 14 20:17 /dev/gpiochip1
RP board top

Red Pitaya board top showing GPIO pins in expansion connectors

Accessing the GPIO device

We make use of the Python periphery module to access the GPIO device.

$ python
Python 3.9.7 (default, Sep 19 2021, 17:26:23)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from periphery import GPIO
>>>
>>> gpio_in = GPIO("/dev/gpiochip1", 1, "in")
>>> gpio_out = GPIO("/dev/gpiochip1", 2, "out")
>>>
>>> value = gpio_in.read()
>>> value
False
>>> gpio_out.write(not value)
>>>
>>> gpio_in.close()
>>> gpio_out.close()

Useful tools

The gpiod package contains a number of tools which are useful when dealing with Linux GPIO devices.

sudo apt-get install gpiod

Manpages of gpiod in Debian bullseye.