Last active
March 28, 2021 05:08
-
-
Save angww/f6597d58ca39d577fe6f8503c6ce2ba2 to your computer and use it in GitHub Desktop.
This snippet code is to test GPIO on Cubieboard A20
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This snippet code is to test GPIO on Cubieboard A20. | |
The main loop blinks two LEDs waiting a button click (conected in PORT_BTN) via interrupt, | |
using funcion poll and wont consuming 100% of cpu. | |
This code was tested with: | |
* Cubiebord A20 (armv7) | |
* Armbian 21.02.3 (Ubuntu based) | |
* Kernel 5.10.21-sunxi | |
* gcc 9.3.0 | |
Schematic: | |
+---------------+ LED2 | |
1 | VCC 5V | PH15 | ---<220_Ohm>------------->|--------+ | |
2 | | PH14 | ---<220_Ohm>--------+ | | |
3 | | PB18 | | LED1 | | |
. | . | . | BTN +---->|--------+ | |
. | . | . | ___|___ | | |
. | . | . | +--o o----------------------+ | |
10 | GND | GND | | | | |
. | . | . | | | | |
. | . | . | | GND | |
. | . | . | | | |
21 | | PE08 | ---+----<2k2_Ohm>----o VCC | |
22 | | PE09 | | |
23 | | PE10 | | |
24 | | PE11 | | |
+---------------+ | |
* Using 2k2 pull up resistor. Cubieboard have internal pull up in someones PINs, but in this moment I dont | |
know how configure it. | |
Pin reference: https://linux-sunxi.org/A20/PIO | |
Pin reference 2: https://abhinavgupta2812.files.wordpress.com/2013/08/gpio_defination_large.jpg | |
Pool function reference: https://man7.org/linux/man-pages/man2/ppoll.2.html | |
Author: Angelo Araujo | |
Date: 2021-03-27 | |
*/ | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <poll.h> | |
#include <signal.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <string.h> | |
/* Main defines. You can change here for your tests */ | |
#define PORT_BTN 238 /* PH14 = 238 */ | |
#define PORT_LED1 239 /* PH15 = 239 */ | |
#define PORT_LED2 136 /* PE08 = 136 */ | |
/* IN OUT used in direction function */ | |
#define IN 1 | |
#define OUT 0 | |
/* NONE BOTH FALLING used in edge funcion */ | |
#define NONE 0 | |
#define BOTH 1 | |
#define FALLING 2 | |
#define RISING 3 | |
/* EXPORT UNERPORT used in export funcion */ | |
#define EXPORT 0 | |
#define UNEXPORT 1 | |
/* Acessory funcion. This converts to string */ | |
#define STR_(X) #X | |
/* Acessory funcion. This makes sure the argument is expanded before converting to string */ | |
#define STR(X) STR_(X) | |
/* Wait time test to the things works */ | |
#define WAIT_TIME 1 | |
/* poll wait time */ | |
#define TIME_MS_POLL_WAIT 500 | |
/* Var used to stop loop with ctrl + c (SIGINT) */ | |
static int keepRunning = 1; | |
/* Acessory funcion. Used to stop main loop. */ | |
void sig_handler(int signo) { | |
if (signo == SIGINT) { | |
keepRunning = 0; | |
} | |
} | |
/* Support funcions */ | |
/* Export example: echo 239 > /sys/class/gpio/export */ | |
void gpio_export(int port_num, int export_unexport) { | |
int fd, w; | |
char s_port[4], s_path[50]; | |
sprintf(s_path, "/sys/class/gpio/%s", (export_unexport ? "unexport" : "export")); | |
sprintf(s_port, "%d", port_num); | |
fd = open(s_path, O_WRONLY); | |
w = write(fd, s_port, 4); | |
printf("EXPORT PIN %s exit: %d\n", s_port, w); | |
if (w == -1) { | |
printf("errno: %d - %s \n", errno, strerror(errno)); | |
} | |
close(fd); | |
} | |
/* Direction example: echo out > /sys/class/gpio/gpio239/direction */ | |
void gpio_set_direction(int port_num, int in_or_out) { | |
int fd, w; | |
char s_path[50]; | |
sprintf(s_path, "/sys/class/gpio/gpio%d/direction", port_num); | |
fd = open(s_path, O_WRONLY); | |
w = write(fd, in_or_out == 1 ? "in" : "out", 6); | |
printf("DIRECTION PIN %d exit: %d\n", port_num, w); | |
close(fd); | |
} | |
/* Edge example: echo both > /sys/class/gpio/gpio239/edge */ | |
void gpio_set_edge(int port_num, int edge) { | |
int fd, w; | |
char s_path[50]; | |
sprintf(s_path, "/sys/class/gpio/gpio%d/edge", port_num); | |
fd = open(s_path, O_WRONLY); | |
w = write(fd, "both", 5); | |
printf("EDGE PIN %d exit: %d\n", port_num, w); | |
close(fd); | |
} | |
/* Set value example: echo 1 > /sys/class/gpio/gpio239/value */ | |
void gpio_set_value(int port_num, int value) { | |
int fd; | |
char s_path[50], s_value[5]; | |
sprintf(s_path, "/sys/class/gpio/gpio%d/value", port_num); | |
sprintf(s_value, "%d", value); | |
fd = open(s_path, O_WRONLY); | |
write(fd, s_value, 4); | |
close(fd); | |
} | |
int main(){ | |
int i = 0, fd, ret; | |
char c; | |
struct pollfd pfd; | |
/* SINGAL HANDLER */ | |
if (signal(SIGINT, sig_handler) == SIG_ERR) { | |
printf("\nOps! Can't catch SIGINT.\n"); | |
} | |
/* Enable GPIO */ | |
gpio_export(PORT_BTN, EXPORT); | |
gpio_export(PORT_LED1, EXPORT); | |
gpio_export(PORT_LED2, EXPORT); | |
/* Set direction of GPIO pins */ | |
gpio_set_direction(PORT_BTN, IN); | |
gpio_set_direction(PORT_LED1, OUT); | |
gpio_set_direction(PORT_LED2, OUT); | |
/* Sleep is needed for correct function. If remove wont work. */ | |
sleep(WAIT_TIME); | |
gpio_set_edge(PORT_BTN, BOTH); | |
/* Wait for event, repeat (i) times */ | |
fd = open("/sys/class/gpio/gpio" STR(PORT_BTN) "/value", O_RDONLY); | |
pfd.fd = fd; | |
pfd.events = POLLPRI; | |
/* Main loop, won't consume 100% cpu. */ | |
while (1) { | |
i++; | |
/* Blink LEDs inverse */ | |
gpio_set_value(PORT_LED1, (i) % 2); | |
gpio_set_value(PORT_LED2, (i+1) % 2); | |
lseek(fd, 0, SEEK_SET); | |
/* int poll(struct pollfd *fds, nfds_t nfds, int timeout); */ | |
ret = poll(&pfd, 1, TIME_MS_POLL_WAIT); | |
read(fd, &c, sizeof(c)); | |
printf("%6d : ", i); | |
if (ret == 0) { | |
printf("Timeout OK\n"); | |
} else { | |
if(c == '0') { | |
printf("-------------------------------------------@@@@@ Push (Readed value of c: %d)\n", c); | |
/* Set 1. Turn on LEDS on button push for 1 second. */ | |
gpio_set_value(PORT_LED1, 1); | |
gpio_set_value(PORT_LED2, 1); | |
sleep(0.7); | |
} | |
else { | |
printf("------------------@@@@@ Release (Readed value of c: %d)\n", c); | |
} | |
} | |
if (keepRunning == 0) { | |
printf("\n Stoped by Ctrl+C (SIGINT). \n"); | |
break; | |
} | |
} | |
close(fd); | |
gpio_export(PORT_BTN, UNEXPORT); | |
gpio_export(PORT_LED1, UNEXPORT); | |
gpio_export(PORT_LED2, UNEXPORT); | |
return(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment