Packages

Pure Elixir library to control and async communicate with the PRU-ICSS cores on BeagleBone Boards.

Current section

Files

Jump to
beagle_pru_interface lib beagle_pru_system.ex
Raw

lib/beagle_pru_system.ex

defmodule BeaglePru.System do
require Logger
@moduledoc """
BeagleBone Black/Green/Pocket PRU Helper Library
"""
defguard is_valid_pru?(coreid) when coreid >= 0 and coreid <= 1
def configure_pins do
run("config-pin overlay cape-universal ")
run("config-pin overlay cape-univ-hdmi ")
:ok
end
def configure_rpmsg do
run("modprobe rpmsg_pru")
:ok
end
# Sysfs location from kernel 4.9
def sysfs_path(0), do: "/sys/class/remoteproc/remoteproc1"
def sysfs_path(1), do: "/sys/class/remoteproc/remoteproc2"
def sysfs_path(id), do: raise("Unknown PRU: #{inspect(id)}")
@doc """
Load and boot a given firmware for on a given PRU processor core.
Returns ':ok'
## Examples
iex> BealgePru.System.boot 0
:ok
"""
def boot(core), do: boot(core, "am335x-pru#{core}-fw")
def boot(core, firmware) when is_valid_pru?(core) do
run("echo '#{firmware}' > #{sysfs_path(core)}/firmware")
run("echo 'start' > #{sysfs_path(core)}/state")
:ok
end
def boot(core, _firmware), do: raise("Unknown PRU: #{inspect(core)}")
@doc """
Stop a given PRU processor core.
Returns ':ok'
## Examples
iex> BealgePru.System.stop 0
:ok
"""
def stop(core) when is_valid_pru?(core) do
run("echo 'stop' > #{sysfs_path(core)}/state")
:ok
end
def stop(core), do: raise("Unknown PRU: #{inspect(core)}")
@doc """
Reboots a given PRU processor core.
Returns ':ok'
## Examples
iex> BealgePru.System.reboot 0
:ok
"""
def reboot(core) do
:ok = stop(core)
:ok = boot(core)
:ok
end
@doc """
Enables the specified pin for use as a GPIO output for the PRUs.
Returns ':ok'
## Examples
iex> BealgePru.System.pin 'P8_11', :out
:ok
iex> BealgePru.System.pin 'P8_11', :in
:ok
"""
def pin(pin, :pruout), do: set_pin(pin, :pruout)
def pin(pin, :pruin), do: set_pin(pin, :pruin)
def pin(pin, :input), do: set_pin(pin, :gpio_input)
def pin(pin, :output), do: set_pin(pin, :gpio_output)
def pin(pin, :gpio), do: set_pin(pin, :gpio)
def pin(pin, cmd), do: set_pin(pin, cmd)
def pin_info(pin) do
import String
case :os.cmd('config-pin -i #{pin}') do
"Invalid pin:" <> _rem ->
{:error, :invalid_pin, pin}
"Pin is not modifyable:" <> _res ->
{:ok, %{pin_modifyable: false}}
response ->
pin_info =
response
|> split("\n")
|> Enum.each(fn s -> [k, v] = split(s, ":"); {k |> downcase() |> trim, v |> downcase |> trim} end)
with {:ok, pin_name} <- Map.fetch(pin_info, "pin name"),
{:ok, gpio_id} <- Map.fetch(pin_info, "kernel gpio id"),
{:ok, gpio_number} <- gpio_id |> Integer.parse(),
{:ok, pru_id} <- Map.fetch(pin_info, "pru gpio id"),
{:ok, pru_number} <- pru_id |> Integer.parse(),
{:ok, default_state} <- Map.fetch(pin_info, "function if no cape loaded"),
{:ok, cape_funcs} <- Map.fetch(pin_info, "function if cape loaded"),
{:ok, pin_funcs} <- Map.fetch(pin_info, "function information")
do
pin_info = %{
name: pin_name,
gpio_id: gpio_number,
pru_id: pru_number,
default: pin_funcs |> trim(),
functions: %{
standard: pin_funcs |> split(" "),
cape: cape_funcs |> split(" "),
default: default_state,
},
status: :os.cmd('config-pin -q #{pin}')
}
{:ok, pin_info}
end
end
end
defp set_pin(pin, cmd) do
run("config-pin #{pin} #{cmd}")
:ok
end
def run(cmd) do
Logger.info(:os.cmd(cmd |> to_charlist))
:os.timestamp()
end
def run(cmd, :raw) do
IO.puts(:os.cmd(cmd |> to_charlist))
:os.timestamp()
end
end