====== GPIO Interrupts ======
===== Introduction =====
The page leads you to use GPIO interrupts with the GPIO number test program on Khadas SBC.
Here we use ''GPIOH_6'' on VIM3 as an example.
===== Hardware Connection =====
Connect the physical pins ''PIN20'' and ''PIN15'' by using a DuPont line.
===== System Configuration =====
Get ''GPIOH_6'' number
Refer to [[/products/sbc/vim4/applications/gpio/40pin-header|40-Pin Header]], the GPIO number you get is ''433''.
Export GPIO
```shell
$ echo 433 | sudo tee /sys/class/gpio/export
```
Please use ''gpio readall'' to check the status of ''GPIOH_6'', if it is not shown as a normal GPIO, you need to remove ''uart3'' from ''overlays'' in file ''/boot/env.txt''. \\
Check the [[products:sbc:vim4:configurations:device-tree-overlay|Device Tree Overlay]] for more details.
===== Demo Source Code =====
Get demo source code
```c gpio_interrupts.c
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2022 Wesion Technology Co., Ltd.
*
* Author: Yan
*
*/
#include
#include
#include
#include
#include
#include
#include
#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define MAX_BUF 255
int gpio_export(unsigned int gpio){
int fd, len;
char buf[MAX_BUF];
fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Can't export GPIO %d pin: %s\n", gpio, strerror(errno));
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
int gpio_unexport(unsigned int gpio){
int fd, len;
char buf[MAX_BUF];
fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Can't unexport GPIO %d pin: %s\n", gpio, strerror(errno));
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
int gpio_set_edge(unsigned int gpio, char *edge){
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Can't set GPIO %d pin edge: %s\n", gpio, strerror(errno));
return fd;
}
write(fd, edge, strlen(edge)+1);
close(fd);
return 0;
}
int gpio_set_pull(unsigned int gpio, char *pull){
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/pull", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "Can't set GPIO %d pin pull: %s\n", gpio, strerror(errno));
return fd;
}
write(fd, pull, strlen(pull)+1);
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
struct pollfd fdset[2];
int fd, ret, gpio;
char buf[MAX_BUF];
if (argc < 3 || argc > 4) {
fprintf(stdout, "usage : sudo sysfs_irq_test [pull]\n");
fflush(stdout);
return -1;
}
gpio = atoi(argv[1]);
if (gpio_export(gpio)) {
fprintf(stdout, "error : export %d\n", gpio);
fflush(stdout);
return -1;
}
if (gpio_set_edge(gpio, argv[2])) {
fprintf(stdout, "error : edge %s\n", argv[2]);
fflush(stdout);
return -1;
}
if (argv[3] && gpio_set_pull(gpio, argv[3])) {
fprintf(stdout, "error : pull %s\n", argv[3]);
fflush(stdout);
return -1;
}
snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_RDWR);
if (fd < 0)
goto out;
while (1) {
memset(fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = fd;
fdset[1].events = POLLPRI;
ret = poll(fdset, 2, 3*1000);
if (ret < 0) {
perror("poll");
break;
}
fprintf(stderr, ".");
if (fdset[1].revents & POLLPRI) {
char c;
(void)read (fd, &c, 1) ;
lseek (fd, 0, SEEK_SET) ;
fprintf(stderr, "\nGPIO %d interrupt occurred!\n", gpio);
}
if (fdset[0].revents & POLLIN)
break;
fflush(stdout);
}
close(fd);
out:
if (gpio_unexport(gpio)) {
fprintf(stdout, "error : unexport %d\n", gpio);
fflush(stdout);
}
return 0;
}
```
Compile the source code
```shell
$ gcc -o gpio_interrupts gpio_interrupts.c
```
===== Demonstrate =====
The test code running format is as follows:
```shell
$ sudo ./gpio_interrupts [pull]
```
Run test:
```shell
$ sudo ./gpio_interrupts rising down
.
GPIO 433 interrupt occurred!
..
GPIO 433 interrupt occurred!
.
GPIO 433 interrupt occurred!
.
GPIO 433 interrupt occurred!
```