3

I am using Linux (kernel 5.8.17) on an embedded custom board and have a script doing some gpioget and gpioset operations with the libgpiod package. Setting output pins with gpioset works great, as does getting value of input pins with gpioget. But when I need to know the current value of an output pin, using gpioget changes the pin value, and the direction.

Here is an example:

~# gpioinfo |grep MB_AC_ON
        line 230:   "MB_AC_ON"       unused  output  active-high
~# gpioset $(gpiofind "MB_AC_ON")=1
~# gpioget $(gpiofind "MB_AC_ON")
   0
~# gpioinfo |grep MB_AC_ON
        line 230:   "MB_AC_ON"       unused   input  active-high

Setting the pin to '1' works. But then checking the current value of that same pin using gpioget, the value changes to '0' and the direction is changed to input. Is it even possible to get the value of a gpio output using libgpiod?

sRuby
  • 33
  • 1
  • 6
  • From my ***"vast experience"*** (used it for the first time today :) with `gpioset`, it seems to me you've got an incorrect assumption in your question" `"using gpioget changes the pin valuet".` I think what is happening is that `gpioset` sets the pin HI, but immediately "releases" it, so it returns to LO. `gpioget` seems to work OK for me - it reports the status correctly, because `gpioset` has already let it go LO; i.e. `gpioset` is not latched. So odd... –  Mar 07 '22 at 05:39

2 Answers2

1

when I checked the detail by gpioset -h there was a note: I think this is the answer to your question.

Note: the state of a GPIO line controlled over the character device reverts to default when the last process referencing the file descriptor representing the device file exits. This means that it's wrong to run gpioset, have it exit and expect the line to continue being driven high or low. It may happen if given pin is floating but it must be interpreted as undefined behavior.

Also if we look at the code(gpioset: ../libgpiod/tools/gpioset.c) in more detail. We can see that these code blocks below, which lead to the line getting default value(you cannot keep the value you set using by gpioset).

    gpiod_line_release_bulk(lines);
    gpiod_chip_unref(chip);
    gpiod_line_bulk_free(lines);
    free(offsets);
    free(values);
Zafer SEN
  • 105
  • 1
  • 12
  • Oh right! That makes sense. Thanks for pointing that out! – sRuby Jan 07 '22 at 14:18
  • BFH... OK, I get it, but you shouldn't have to get that fm a header file - esp when there's a `--help` option. It also means the `--help` and `man gpioset` are incorrect as they list the `mode` as an optional argument. Bad boy Bartosz. And thanks Zafer! –  Mar 07 '22 at 01:06
  • And now that you've sussed the `problem` (well, at least I say it's a problem) it would be great if someone submitted a PR (or branch `gpioset`) to get something that behaves in a more conventional fashion?? hint, hint –  Mar 07 '22 at 01:19
1

Actually the accepted answer contains only one aspect of the problem. Yes, gpioset doesn't guarantee to persist the GPIOs state after exit. One could use the mode parameter to keep the file descriptor open until it receives a signal.[1]

gpioset --mode=signal $(gpiofind "MB_AC_ON")=1

For libgpiod v2 gpioset behaves differently and doesn't exit by default anymore unless it receives a signal. With other simplifications to directly specify a line by label, the equivalent command as above boils down to the following in v2:

gpioset MB_AC_ON=1

Though for some GPIO controllers the state is actually persistent even after gpioset exits, which also seems to be the case for the OP. In those cases you still have the problem that using gpioget afterwards changes the direction from output back to input, even when you just want to get the current state of the output.

In this case v2 of libgpiod has a new parameter --as-is to keep the direction[2]:

gpioget --as-is MB_AC_ON

[1] https://manpages.debian.org/testing/gpiod/gpioset.1.en.html
[2] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/commit/tools/gpioget.c?h=v2.0&id=3a912fbc1e2697f4479396fd11557b943b31d217

frsc
  • 406
  • 3
  • 11