Originally posted by me on May 15, 2017
GPIO is probably one of the most easiest things to work with on a beaglebone. Once you understand a few things. First, the kernel through sysfs has no idea what pins are tied to which header pin. So one needs to find a spread sheet that will explain which header pin is attached to which GPIO pin through the sysfs file structure. The base path for the sysfs gpio path is /sys.class/gpio/. However the explanation of how all this works is fairly lengthy, and there are a lot of guides dating back to the original bealgebone(white) as to how all this works. In short, if you need to know this information I suggest you search the web for information. This is the “manual” way of setting up GPIO.
Another alternative is again to use a device tree overlay file. Which in of it’s self is initially a lengthy process to understand. In short: https://github.com/beagleboard/bb.org-overlays/blob/master/src/arm/univ-nhdmi-00A0.dts#L232-#L234 The highlighted text here is defining a pin number, and the mode that pin needs to be set into for GPIO operation, with pullup, and RxActive enabled. These files for the purpose of this explanation are not exactly the best to use. Perhaps at some point in the future Ill create a simple overlay file, for the purpose of better explanation. As it is, this particular overlay is for Universal IO, and it covers most, if not all pins, with most if not all possible modes for each pin. Used with config-pin this allows one to configure each pin as needed dynamically from the command line . . .
So onto some simple code. First, again, some explanation is required. For our board we have some PWM pins, and some input pins, among other things. Both PWM, and input only use 6 pins each. In order to test the circuitry of our boards, To test the our capes circuitry, we instead use the PWM pins as GPO’s, the input pins as GPI’s, and have a test header connecting each “zone” together from GPO to GPI. Additionally, there is an LED connected to each GPO on this test header for visual inspection.
Code:
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#define HIGH 1
#define LOW 0
#define PWM1 2
#define PWM2 3
#define PWM3 50
#define PWM4 22
#define PWM5 51
#define PWM6 23
#define Z1IN 44
#define Z2IN 45
#define Z3IN 46
#define Z4IN 47
#define Z5IN 48
#define Z6IN 49
void set_pin(int pin_num, int value)
{
char gpio_path[40] = {0};
char str_value[2] = {0};
sprintf(str_value, "%d", value);
sprintf(gpio_path, "/sys/class/gpio/gpio%d/value", pin_num);
int fd = open(gpio_path, O_WRONLY);
if(fd == -1){
perror(gpio_path);
exit(1);
}
int nread = write(fd, str_value, 1);
if( nread < 0){
perror("write()");
exit(1);
}
close(fd);
}
int get_pin(int pin_num)
{
char gpio_path[40] = {0};
char str_value[2] = {0};
sprintf(gpio_path, "/sys/class/gpio/gpio%d/value", pin_num);
int fd = open(gpio_path, O_RDONLY);
if(fd == -1){
perror(gpio_path);
exit(1);
}
read(fd, str_value, sizeof(str_value - 1));
close(fd);
return strtol(str_value, NULL, 10);
}
int main()
{
set_pin(PWM1, LOW);
set_pin(PWM2, LOW);
set_pin(PWM3, LOW);
set_pin(PWM4, LOW);
set_pin(PWM5, LOW);
set_pin(PWM6, LOW);
sleep(1);
printf("PWM1: %i Z1IN: %i \n", get_pin(PWM1), get_pin(Z1IN));
printf("PWM2: %i Z2IN: %i \n", get_pin(PWM2), get_pin(Z2IN));
printf("PWM3: %i Z3IN: %i \n", get_pin(PWM3), get_pin(Z3IN));
printf("PWM4: %i Z4IN: %i \n", get_pin(PWM4), get_pin(Z4IN));
printf("PWM5: %i Z5IN: %i \n", get_pin(PWM5), get_pin(Z5IN));
printf("PWM6: %i Z6IN: %i \n", get_pin(PWM6), get_pin(Z6IN));
printf("\n");
/***********************************************************/
set_pin(PWM1, HIGH);
set_pin(PWM2, HIGH);
set_pin(PWM3, HIGH);
set_pin(PWM4, HIGH);
set_pin(PWM5, HIGH);
set_pin(PWM6, HIGH);
sleep(1);
printf("PWM1: %i Z1IN: %i \n", get_pin(PWM1), get_pin(Z1IN));
printf("PWM2: %i Z2IN: %i \n", get_pin(PWM2), get_pin(Z2IN));
printf("PWM3: %i Z3IN: %i \n", get_pin(PWM3), get_pin(Z3IN));
printf("PWM4: %i Z4IN: %i \n", get_pin(PWM4), get_pin(Z4IN));
printf("PWM5: %i Z5IN: %i \n", get_pin(PWM5), get_pin(Z5IN));
printf("PWM6: %i Z6IN: %i \n", get_pin(PWM6), get_pin(Z6IN));
return 0;
}
Output:
root@wgd:~/dl-i2c-test# gcc -Wall -o read_zonein read_zonein.c
root@wgd:~/dl-i2c-test# ./read_zonein
PWM1: 0 Z1IN: 1
PWM2: 0 Z2IN: 1
PWM3: 0 Z3IN: 1
PWM4: 0 Z4IN: 1
PWM5: 0 Z5IN: 1
PWM6: 0 Z6IN: 1
PWM1: 1 Z1IN: 0
PWM2: 1 Z2IN: 0
PWM3: 1 Z3IN: 0
PWM4: 1 Z4IN: 0
PWM5: 1 Z5IN: 0
PWM6: 1 Z6IN: 0
As one can see the logic between inputs, and output is reversed. This is of course intentional.