CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5

Thread: [RESOLVED] sysfs GPIO Interrupts

  1. #1
    Join Date
    Feb 2018

    [RESOLVED] sysfs GPIO Interrupts

    Morning all,

    First post on codeguru, I looking forward to learning and contributing!

    I'm having some issues with a c++ function I'm using to monitor for GPIO interrupts on a generic Linux device. I'm providing a square wave signal of known frequency to a GPIO pin, but the resultant output of the following code is erroneous. If I set the edge detection method to "falling", the calculated frequency is correct. However, if I use "rising" detection, the frequency output is sporadic and incorrect. I'd like to be able to use "both" for the purpose of calculating duty cycle.

    int gpio::interrupts(string gpioNumber)
        int fd;
        int retval;
        struct timeval holder;
        struct timeval tvCurrent;
        double usPrevious;
        double usCurrent;
        double diff;
        struct pollfd pfd;
        char buf[64];
        int error = -1;
        string openD = "/sys/class/gpio/gpio" + gpioNumber + "/value";
        error = fd = open(openD.c_str(), O_RDONLY);
        while (error < 0) {
            error = fd = open(openD.c_str(), O_RDONLY);
        pfd.fd = fd;
        pfd.events = POLLPRI;
        lseek(fd, 0, SEEK_SET);
        while(1) {
            retval = poll(&pfd, 1, -1);
            if (pfd.revents & POLLPRI) {
                lseek(fd, 0, SEEK_SET);
                retval = read(fd, buf, sizeof buf);
                //The following std::cout will be discussed in the following section
                //std::cout << "Thread: " << std::this_thread::get_id() << " GPIO: " << gpioNumber << " Value : " << retval << std::endl;
                gettimeofday(&tvCurrent, NULL);
                //tvPrevious is a list of lists declared in the header
                if (tvPrevious[std::stoi(gpioNumber)][0] != 0 && tvPrevious[std::stoi(gpioNumber)][1] != 0) {
                    usPrevious = (tvPrevious[std::stoi(gpioNumber)][0]*1e6) + tvPrevious[std::stoi(gpioNumber)][1];
                    usCurrent = (tvCurrent.tv_sec*1e6) + tvCurrent.tv_usec;
                    diff = (usCurrent - usPrevious)/1e6;
                    //Replace the previous frequency record for this gpio
                    //in the existing list. The list is declared in the header
                    //and initialised in another function
                    gpioFrequencies.replace(std::stoi(gpioNumber), 1/diff);
                    emit gpioFrequenciesChanged();
                    tvPrevious[std::stoi(gpioNumber)][0] = tvCurrent.tv_sec;
                    tvPrevious[std::stoi(gpioNumber)][1] = tvCurrent.tv_usec;
                    tvCurrent.tv_sec = 0;
                    tvCurrent.tv_usec = 0;
                } else {
                    gettimeofday(&holder, NULL);
                    tvPrevious[std::stoi(gpioNumber)][0] = holder.tv_sec;
                    tvPrevious[std::stoi(gpioNumber)][1] = holder.tv_usec;
                    holder.tv_sec = 0;
                    holder.tv_usec = 0;
        return 0;
    A secondary issue I have with the above code is in reading the gpio value from the /sys/class/gpio/gpioX/value file. The commented std::cout in the above code is used to ensure each gpio is running on a single, detached thread, and to read the value of the gpio's /value file. Whether I use "rising", "falling" or "both" for edge detection, the value of retval is always 2. I expect the value to be either 1 (HIGH) or 0 (LOW).

    In summary, my two questions are as follows:

    1. How can I amend the above code to ensure not only "falling" detection works, but "rising" and "both" as well?
    2. How can I amend the above code to ensure a successful, valid reading of the /value file once the interrupt has been triggered?

  2. #2
    Join Date
    Feb 2018

    Re: sysfs GPIO Interrupts

    I've managed to address question number 2, by adding the following lines after retval = read(fd, buf, sizeof buf);:

    string output = string(buf);
    output now holds the correct 1 (HIGH) or 0 (LOW) value of the specified GPIO.

  3. #3
    Join Date
    Feb 2018

    Re: sysfs GPIO Interrupts

    I've figured out the issue of the fluctuating frequency measurement as well. It turns out the interrupt was being called for both rising and falling edges, which meant the period measurement was incorrect. Now that I'm able to read the GPIO value correctly, it was pretty easy to identify the issue.

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012

    Re: sysfs GPIO Interrupts

    It looks like you are expecting only a single char read from the file? In this case consider

    retval = read(fd, buf, 1);
    buf[1] = 0;
    if (retval != 1)
       cout << "Error reading fd" << endl;
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2017 (15.9.4)

  5. #5
    Join Date
    Feb 2018

    Re: [RESOLVED] sysfs GPIO Interrupts

    Thanks for your input 2kaud. I'm quite new to c++, so will happily play around with alternative methods of reading the GPIO value. I'll give your approach a go this evening.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Windows Mobile Development Center

Click Here to Expand Forum to Full Width

On-Demand Webinars (sponsored)