How to control the GPIO?

How to control the GPIO?
Are you planning to introduce your own version eg WiringPi?

Hi,

We plan to port libmraa on ROCK Pi 4, which we think it’s a more professional project.

On this moment can’t use Gpio?

Mraa is quite demanding compared to wiringpi

If you’re into C, I would check out TinyGPIO on the Pi… https://github.com/dasfoo/rpi-gpio/blob/master/gpio.c (there are newer versions on the net too) you can just change the hardware addresses and start hacking i guess. Even more low level (which should also work on the RockPi): https://elinux.org/RPi_GPIO_Code_Samples#Direct_register_access

RK3399 datasheet, Section 20.4 http://opensource.rock-chips.com/images/e/ee/Rockchip_RK3399TRM_V1.4_Part1-20170408.pdf

Rockchip GPIO has 5 banks, GPIO0~GPIO4, each bank has 32pins, naming as below:

GPIO0_A0 ~ A7 
GPIO0_B0 ~ B7
GPIO0_C0 ~ C7
GPIO0_D0 ~ D7

GPIO1_A0 ~ A7
....
GPIO1_D0 ~ D7

For Rockchip 4.4 kernel, the GPIO number can be calculated as below, take GPIO4_D5(PIN22 on 40PIN GPIO) as an example:

GPIO4_D5 = 32*4 + 8*3 + 5 = 157

To set GPIO4_D5 output

cd /sys/class/gpio
echo 157 > export
cd gpio157
echo out > direction
echo 1 > value     # output high
echo 0 > value     # output low
1 Like

Tipp:

You can set the output value of an output and configuring the pin as a output in one command:

# Sets the pin as output and sets it to logical HIGH
echo "high" > /sys/class/gpio/gpio157/direction
# Sets the pin as output and sets it to logical LOW
echo "low" > /sys/class/gpio/gpio157/direction
3 Likes

GPIO pin number can be simplified by below table

3 Likes

Nice. i will add it to the wiki :slight_smile:

1 Like

I implemented a Python wrapper for the GPIOs. One thing to observe is to make a call to seek(0), otherwiese the pins will not show the change in state.

GPIO class:

import os
from subprocess import run
from time import sleep

class GPIO:
    """ class to initialize and switch GPIO pins """
    def __init__(self, gpio_pin):
        """ :param gpio_pin: either a string of the form "GPIO3_D5" where 3 is the bank number  and D5 the address name, or, an integer """

        if type(gpio_pin) == str:
            if not self.parse_gpio_pin(gpio_pin):
                raise ValueError
        elif type(gpio_pin) == int:
            self.pin_number = str(gpio_pin)
        else:
            raise ValueError

        self.pin_dir = "gpio" + self.pin_number  # /sys/class/gpio pin directory name
        self.pin = None  # file descriptor for pin

    def parse_gpio_pin(self, gpio_pin):
         """ parses the input parameter """
        parts = gpio_pin.split('_')
        if len(parts) == 2 and len(parts[0]) == 5 and len(parts[1]) == 2:
            try:
                bank = int(parts[0][4])
            except ValueError:
                return False

            address1_coding = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
            try:
                address1 = address1_coding[parts[1][0]]
            except KeyError:
                return False

            try:
                address2 = int(parts[1][1])
            except ValueError:
                return False

            self.pin_number = str(bank * 32 + address1 * 8 + address2)
            return True

        else:
            return False

    def configure(self):
        """ configure pin for output """
        if not os.path.exists('/sys/class/gpio/' + self.pin_dir):
            subprocess.run('echo ' + self.pin_number + ' > ' + '/sys/class/gpio/export', shell=True)
        subprocess.run('echo out' + ' > ' + '/sys/class/gpio/' + self.pin_dir + '/direction', shell=True)

    def open(self):
        """ open pin directory for writing """
        self.pin = open('/sys/class/gpio/' + self.pin_dir + '/value', 'w')

    def switch(self, on):
        """ function to set pin high or low"""
        if on is True:
            self.pin.write('1')
        else:
            self.pin.write('0')
        # writing becomes effective only after a seek(0):
        self.pin.seek(0)

    def close(self):
        """ close pin directory """
        if self.pin is not None and not self.pin.closed:
            self.pin.close()

    def __del__(self):
        """ automatic closing on object deletion """
        self.close()

Usage:

# test with pin for red on-board LED
gpio = GPIO("GPIO3_D5")
gpio.configure()
gpio.open()

for i in range(10):
    gpio.switch(True)
    sleep(1)
    gpio.switch(False)
    sleep(1)

Somehow it doesn’t work in my build (Debian ARM64 + DTB from armhf).

The red LED is on in Debian ARM64 and off in armhf by default, after I copied the DTB from armhf to ARM64. I got the audio but the LED turns off. The intfc:dtoverlay=two-color-led setting in /boot/hw_intfc.conf doesn’t seem affect this on neither side. I guess there are some conflicts going on.

The example with the red LED was more to demonstrate the general usage of the GPIO Python class. It can be used to switch any GPIO pin. On my RockPi Armbian system the red LED works.

GPIO_3_D5 = 3 * 32 + 3 * 8 + 5  # = 125
gpio = GPIO(GPIO_3_D5)

If you could parse the name string to convert to number, that would help some people to calculate the numbers.

For newer kernel, the LED is configured as heart beat device. You can not control it. You can control it with led trigger.

cat /sys/class/leds/user-led2/trigger
none rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock mmc0 mmc1 timer oneshot [heartbeat] backlight gpio cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 default-on rfkill0 mmc2 rfkill1 rfkill2

For example, you can set it to emmc read/write status with following:

echo mmc1 >  /sys/class/leds/user-led2/trigger

Good idea, already updated.

HI Jack,
I have problem to activate the GPIO pins on Ubuntu mate desktop with the latest kernel. Could you please have a look at my problem?
https://forum.radxa.com/t/mraa-gpio-list-no-pins/1467

Thanks,
Rolly

Hi friends,

I have a silly question, but I’m not finding the answer.

I’m reading the documentation of the mraa to see if I can learn how to control my gpios. On Raspberry we have to define if we are either going to use the GPIO address or the BOARD address.

Can I do or need to do the same with mraa? What about the gpio.cleanup command ?

Thanks in advance!