简体   繁体   English

如何在Linux板上检测GPIO的引脚变化

[英]how to detect a pin change of a GPIO on Linux board

I am using 3.12 kernel on an ARM based linux board (imx233 CPU). 我在基于ARM的linux板(imx233 CPU)上使用3.12内核。 My purpose is to detect pin change of a GPIO (1 to 0). 我的目的是检测GPIO的引脚变化(1到0)。

I can read the pin value constantly calling the below function (in a while(1) loop) 我可以不断调用下面的函数读取引脚值(在while(1)循环中)

int GPIO_read_value(int pin){
    int gpio_value = 0;
    char path[35] = {'\0'};
    FILE *fp;
    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if ((fp = fopen(path,"rb+")) == NULL){ //echo in > direction
         //error
    }

    fscanf(fp, "%d", &gpio_value);
    fclose(fp);
    return gpio_value;
}

But it causes too much load to the CPU. 但它会给CPU带来太多负载。 I don't use usleep or nanosleep , because the pin change happens for a very short of a time that would cause me to miss the event. 我不使用usleepnanosleep ,因为引脚更改会在很短的时间内发生,这会导致我错过事件。

As far as I find out, it is not possible to use poll() . 据我所知,不可能使用poll() Is there any poll() like function that I can use to detect a pin change of a GPIO? 是否有任何poll()函数可用于检测GPIO的引脚变化?

EDIT: Just in case, if I am doing something wrong, here is my poll() usage that does not detect the pin change 编辑:以防万一,如果我做错了,这是我的poll()用法,不检测引脚更改

struct pollfd pollfds;
    int fd;
    int nread, result;
    pollfds.fd = open("/sys/class/gpio/gpio51/value", O_RDWR);
    int timeout = 20000;           /* Timeout in msec. */
    char buffer[128];

    if( pollfds.fd < 0 ){
        printf(" failed to open gpio \n");
        exit (1);
    }

    pollfds.events = POLLIN;
    printf("fd opens..\n");
    while (1)
    {
            result = poll (&pollfds, 0, timeout);
            switch (result)
            {
                  case 0:
                    printf ("timeout\n");
                    break;
                  case -1:
                    printf ("poll error \n");
                    exit (1);

                   default:
                printf("something is happening..\n");
                    if (pollfds.revents & POLLIN)
                    {
                        nread = read (pollfds.fd, buffer, 8);
                        if (nread == 0) {
                            printf ("result:%d\n", nread);
                            exit (0);
                         } else {
                            buffer[nread] = 0;
                            printf ("read %d from gpio: %s", nread, buffer);
                         }
                     }
              }
     }
     close(fd);

EDIT2: the code on https://developer.ridgerun.com/wiki/index.php/Gpio-int-test.c works fine with poll() I needed to define the rising/falling edge for the interrupt and a little bit fix on the definition. EDIT2: https : //developer.ridgerun.com/wiki/index.php/Gpio-int-test.c上的代码与poll()一起工作正常我需要定义中断的上升沿/下降沿和一点点修复定义。 It solves my problem, however, it might be good for me and some other people to hear/know the alternative methods. 它解决了我的问题,然而,对我和其他一些人来说,听听/了解替代方法可能会有好处。

I have never seen this board before, however I guess PIC is fully implemented for this board (usually is like that) but you have to configure interrupt additionally in GPIO controller (usually is like that). 我之前从未见过这块板,但是我觉得PIC完全实现了这块板(通常就是这样)但你必须在GPIO控制器中另外配置中断(通常就是这样)。 Some part should be done as a kernel module, then you have to pass information about interrupt to you application. 某些部分应该作为内核模块完成,然后您必须将有关中断的信息传递给您的应用程序。

Example way to do this is to implement following thing as a kernel module: 这样做的示例方法是将以下内容实现为内核模块:

  • setup GPIO controller to enable interrupt on particular port and level (how to do this you can find here: http://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf 37.2.3.3 Input Interrupt Operation) 设置GPIO控制器以在特定端口和级别上启用中断(如何执行此操作,您可以在此处找到: http ://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf 37.2.3.3输入中断操作)

  • enable GPIO interrupt in PIC (how to do this: http://lwn.net/images/pdf/LDD3/ch10.pdf Chapter10) 在PIC中启用GPIO中断(如何执行此操作: http//lwn.net/images/pdf/LDD3/ch10.pdf第10章)

  • implement interrupt handling routine (I will describe a little bit below) 实现中断处理程序(我将在下面介绍一下)
  • implement ioctl interfaces for your module. 为您的模块实现ioctl接口。

and a rest in your application: 并在您的申请中休息:

  • a function that can coosomeoneperate with interrupt. 可以通过中断进行共同操作的功能。

Simplest way of passing information about interrupt from kernel to app is by semaphore on kernel side. 从内核到应用程序传递有关中断的信息的最简单方法是在内核端通过信号量传递。 in module you can implement an ioctl that will sleep until interrupt happen. 在模块中,您可以实现一个睡眠直到中断发生的ioctl。 So application will call this ioctl and its thread will be blocked until interrupt happen. 所以应用程序将调用此ioctl,其线程将被阻塞,直到发生中断。

Inside module, interrupt routine should check if application thread is now blocked, and if so up() semaphore. 在内部模块中,中断例程应检查应用程序线程是否现在被阻止,如果是,则()信号量。

EDIT***** 编辑*****

This CPU has SSP that has working mode for SPI. 该CPU具有SSP,具有SPI工作模式。 Why dont use it ?? 为什么不使用它?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM