Elixir Version : 1.6.0 Compiled with OTP 20 Erlang OTP: 20
I installed nerves and created new nerves project when I set MIX_TARGET=rpi3. I get this error
** (FunctionClauseError) no function clause matching in Nerves.Runtime.Kernel.UEvent.handle_info/2
** (FunctionClauseError) no function clause matching in Nerves.Runtime.Kernel.UEvent.handle_info/2
(nerves_runtime) lib/nerves_runtime/kernel/uevent.ex:24: Nerves.Runtime.Kernel.UEvent.handle_info({#Port<0.7405>, {:exit_status, 8}}, %{autoload: true, port: #Port<0.7405>})
(stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:686: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {#Port<0.7405>, {:exit_status, 8}}
State: %{autoload: true, port: #Port<0.7405>}
I looked into the uevent.ex handle_info is defined
defmodule Nerves.Runtime.Kernel.UEvent do use GenServer
require Logger
alias Nerves.Runtime.Device
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(opts) do
autoload = if opts[:autoload_modules] != nil, do: opts[:autoload_modules], else: true
send(self(), :discover)
executable = :code.priv_dir(:nerves_runtime) ++ '/uevent'
port = Port.open({:spawn_executable, executable},
[{:args, []},
{:packet, 2},
:use_stdio,
:binary,
:exit_status])
{:ok, %{port: port, autoload: autoload}}
end
def handle_info(:discover, s) do %%%%LINE 24%%%%%%%
Device.discover
{:noreply, s}
end
def handle_info({_, {:data, <<?n, message::binary>>}}, s) do
msg = :erlang.binary_to_term(message)
handle_port(msg, s)
end
defp handle_port({:uevent, _uevent, kv}, s) do
event =
Enum.reduce(kv, %{}, fn (str, acc) ->
[k, v] = String.split(str, "=", parts: 2)
k = String.downcase(k)
Map.put(acc, k, v)
end)
case Map.get(event, "devpath", "") do
"/devices" <> _path -> registry(event, s)
_ -> :noop
end
{:noreply, s}
end
def registry(%{"action" => "add", "devpath" => devpath} = event, s) do
attributes = Map.drop(event, ["action", "devpath"])
scope = scope(devpath)
#Logger.debug "UEvent Add: #{inspect scope}"
if subsystem = Map.get(event, "subsystem") do
SystemRegistry.update_in(subsystem_scope(subsystem), fn(v) ->
v = if is_nil(v), do: [], else: v
[scope | v]
end)
end
if s.autoload, do: modprobe(event)
SystemRegistry.update(scope, attributes)
end
def registry(%{"action" => "remove", "devpath" => devpath} = event, _) do
scope = scope(devpath)
#Logger.debug "UEvent Remove: #{inspect scope}"
SystemRegistry.delete(scope)
if subsystem = Map.get(event, "subsystem") do
SystemRegistry.update_in(subsystem_scope (subsystem), fn(v) ->
v = if is_nil(v), do: [], else: v
{_, scopes} = Enum.split_with(v, fn(v) -> v == scope end)
scopes
end)
end
end
def registry(%{"action" => "change"} = event, s) do
#Logger.debug "UEvent Change: #{inspect event}"
raw = Map.drop(event, ["action"])
Map.put(raw, "action", "remove")
|> registry(s)
Map.put(raw, "action", "add")
|> registry(s)
end
def registry(%{"action" => "move", "devpath" => new, "devpath_old" => old}, _) do
#Logger.debug "UEvent Move: #{inspect scope (old)} -> #{inspect scope(new)}"
SystemRegistry.move(scope(old), scope(new))
end
def registry(event, _) do
Logger.debug "UEvent Unhandled: #{inspect event}"
end
defp scope("/" <> devpath) do
scope(devpath)
end
defp scope(devpath) do
[:state | String.split(devpath, "/")]
end
defp subsystem_scope(subsystem) do
[:state, "subsystems", subsystem]
end
defp modprobe(%{"modalias" => modalias}) do
System.cmd("modprobe", [modalias], stderr_to_stdout: true)
end
defp modprobe(_), do: :noop
end
Here is mix file
defmodule Powpow.MixProject do
use Mix.Project
@target System.get_env("MIX_TARGET") || "host"
Mix.shell().info([
:green,
"""
Mix environment
MIX_TARGET: #{@target}
MIX_ENV: #{Mix.env()}
""",
:reset
])
def project do
[
app: :powpow,
version: "0.1.0",
elixir: "~> 1.4",
target: @target,
archives: [nerves_bootstrap: "~> 0.7"],
deps_path: "deps/#{@target}",
build_path: "_build/#{@target}",
lockfile: "mix.lock.#{@target}",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
aliases: aliases(@target),
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application, do: application(@target)
# Specify target specific application configurations
# It is common that the application start function will start and supervise
# applications which could cause the host to fail. Because of this, we only
# invoke Powpow.start/2 when running on a target.
def application("host") do
[extra_applications: [:logger]]
end
def application(_target) do
[mod: {Powpow.Application, []}, extra_applications: [:logger]]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[{:nerves, "~> 0.9", runtime: false}] ++ deps(@target)
end
# Specify target specific dependencies
defp deps("host"), do: []
defp deps(target) do
[
{:shoehorn, "~> 0.2"},
{:nerves_runtime, "~> 0.4"}
] ++ system(target)
end
defp system("rpi"), do: [{:nerves_system_rpi, ">= 0.0.0", runtime: false}]
defp system("rpi0"), do: [{:nerves_system_rpi0, ">= 0.0.0", runtime: false}]
defp system("rpi2"), do: [{:nerves_system_rpi2, ">= 0.0.0", runtime: false}]
defp system("rpi3"), do: [{:nerves_system_rpi3, ">= 0.0.0", runtime: false}]
defp system("bbb"), do: [{:nerves_system_bbb, ">= 0.0.0", runtime: false}]
defp system("ev3"), do: [{:nerves_system_ev3, ">= 0.0.0", runtime: false}]
defp system("qemu_arm"), do: [{:nerves_system_qemu_arm, ">= 0.0.0", runtime: false}]
defp system("x86_64"), do: [{:nerves_system_x86_64, ">= 0.0.0", runtime: false}]
defp system(target), do: Mix.raise "Unknown MIX_TARGET: #{target}"
# We do not invoke the Nerves Env when running on the Host
defp aliases("host"), do: []
defp aliases(_target) do
[
# Add custom mix aliases here
]
|> Nerves.Bootstrap.add_aliases()
end
end
Why it is not able to find the definition ?
What is happening here is that Nerves is compiling the product for the target rpi3 or Raspberry Pi 3, therefore, its failing to run on your host machine when you call iex -S mix
. You would have to unset MIX_TARGET
so that you run in "host" mode.
Once you have built your project, you should run mix firmware
mix firmware.burn
and run the project on the target.
Check out our getting started guide for more info on how to deploy and run the project.