steveryan

steveryan

Help opening/closing GPIO pin after nerves crashes

Hello,

I’m getting started developing with Nerves and Circuits.GPIO.

When my program starts I’m calling a function like below, to open GPIO pin 26 for output:

@output_pin Application.compile_env(:Program, :output_pin, 26)

  def setup_gpio() do
    {:ok, output_pin} = GPIO.open(@output_pin, :output)
  end

This has so far worked fine, but when testing something, I crashed the program, and now when I go to re-run it I get the following error:

(MatchError) no match of right hand side value: {:error, :already_open}

Which I take to mean, since the program crashed, it didn’t clean up GPIO pin connection, so it’s still left open. My question is, how do I now do anything with that pin. I have tried closing it, but since I do not have access to the handle I can’t get it to close. (e.g. GPIO.close("GPIO26") gives me an error.

Is there any way, short of unplugging the raspberry pi and plugging it back in that I can either get the handle of this GPIO connection so I can write to it, OR close the connection, so that I can reopen it and capture the handle?

Most Liked

fhunleth

fhunleth

Co-author of Nerves

@jjcarstens A few people have had similar problems when Circuits.GPIO started requiring that there only be one reference per GPIO at a time. I think that Circuits.GPIO will need to be more helpful since it is turning out to affect more people than expected.

In case it’s helps, the happy path for using Circuits.GPIO is to wrap a GPIO or set of GPIOs in a GenServer. The GPIO reference returned by Circuits.GPIO.open/3 should only exist in that GenServer’s state. I.e., don’t return it. (This is what @jjcarstens and @lawik said, but it seemed good to repeat.) When the GenServer crashes, Erlang’s garbage collector will clean up the GPIO reference and that will free up the GPIO to be used when the Supervisor starts it up again. Adding a call to Circuits.GPIO.close/1 in the terminate callback like @lawik says seems nice. Erlang’s garbage collector is normally amazingly quick at cleaning dead processes up should terminate not get called.

The current unhappy path for working with GPIOs is to create an API that returns raw references. This seems like a completely reasonable thing to do, but once the GPIO references get stored in a couple processes, Erlang’s GC will probably think the GPIO is alive when it’s really not.

If the code isn’t performance critical, try using Circuits.GPIO.write_one/3 and Circuits.GPIO.read_one/2 to avoid processes owning references completely. This might be a quick fix.

I filed an issue on Circuits.GPIO since it should be possible to do something without rebooting.

lawik

lawik

Nerves Core Team

I have dealt with this at times by implementing the terminate callback (a GenServer owned the reference) and making sure it tidies up before it dies.

I would assume restarting the BEAM would help..

jjcarstens

jjcarstens

Nerves Core Team

Do you have reproducible code? Typically closed process reference is cleaned up by Circuits. The fact you’re getting that error tells me you may not be opening the GPIO from the same process(es) that crashes, you may be inadvertently trying to open it multiple times on process boot, or a potential bug in Circuits. But I’ll need a little bit more code example to be helpful in figuring that out :pray:

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Other popular topics Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New

We're in Beta

About us Mission Statement