Mix tooling for building, deploying, and updating Elixir applications on
GRiSP boards. It provides the same GRiSP workflows as
rebar3_grisp, adapted to Mix releases and Elixir configuration.
Run mix help grisp.TASK for task-specific help.
- Elixir 1.20 or later
- A local Erlang/OTP installation whose major version matches the target OTP
- A GRiSP 2 board and SD card
- A GRiSP toolchain or Docker when building OTP, eMMC images, or bootloaders
Add GRiSP and this build-time plugin to mix.exs:
defp deps do
[
{:grisp, "~> 2.12"},
{:mix_grisp, "~> 1.0", runtime: false}
]
endFetch dependencies with mix deps.get. Print the installed plugin and library
versions with:
mix grisp.versionThe configure task creates a supervised Mix application with release and GRiSP configuration, plus optional networking files:
mix grisp.configureFor non-interactive use:
mix grisp.configure --no-interactive --name my_grisp_app \
--ssid mywifi --psk wifipskImportant options are --name, --otp-version, --jit true|false, --dest,
--wifi, --ssid, --psk, --grisp-io, --grisp-io-linking TOKEN,
--epmd, and --cookie.
The JIT option uses the rebar-compatible explicit values --jit true and
--jit false. In non-interactive mode, optional features are disabled when
their flags are absent. Ethernet networking is always configured. Wi-Fi is
opt-in through --wifi and is also enabled implicitly when either --ssid or
--psk is supplied. Supplying --grisp-io-linking TOKEN also enables GRiSP.io
integration.
If the target directory already exists, interactive mode asks for confirmation, preserves every existing file, and creates only missing files. Non-interactive mode refuses to configure an existing directory so scripts cannot overwrite a project accidentally.
Add GRiSP and release configuration to the project keyword list:
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.20",
deps: deps(),
grisp: grisp(),
releases: releases()
]
end
defp grisp do
[
platform: :grisp2,
otp: [version: "29", jit: true],
deploy: [
destination: "/path/to/SD-card",
# pre_script: "rm -rf /path/to/SD-card/*",
# post_script: "diskutil unmount /path/to/SD-card"
]
]
end
defp releases do
[
my_app: [
overwrite: true,
cookie: "replace_with_a_long_random_cookie",
include_erts: &MixGrisp.Release.erts/0,
steps: [&MixGrisp.Release.init/1, :assemble],
include_executables_for: [],
strip_beams: Mix.env() == :prod
]
]
end:platform defaults to :grisp2. The configured OTP version requirement
selects a pre-built package unless a :build section enables a custom build.
Compile on the development host with the same OTP major version as the target.
Add grisp/grisp2/common/deploy/files/grisp.ini.mustache. Mix releases need
the RELEASE_LIB boot variable. Elixir also expects native UTF-8 filename
encoding, so -fnu must be passed to erl.rtems. To boot into IEx, use the
Elixir user driver and +iex; -s elixir start_iex is obsolete and fails on
current Elixir releases.
[erlang]
args = erl.rtems -C multi_time_warp -fnu -- -mode embedded -home . -pa . -root {{release_name}} -bindir {{release_name}}/erts-{{erts_vsn}}/bin -boot {{release_name}}/releases/{{release_version}}/start -boot_var RELEASE_LIB {{release_name}}/lib -config {{release_name}}/releases/{{release_version}}/sys.config -kernel inetrc "./erl_inetrc" -user elixir -extra +iex --no-halt
shell = none
on_exit = reboot
on_crash = reboot
[network]
ip_self=dhcp
wlan=enable
hostname=GRISP_HOSTNAME
wpa=wpa_supplicant.confFor Wi-Fi, add wpa_supplicant.conf beside it:
network={
ssid="WLAN_SSID"
key_mgmt=WPA-PSK
psk="WLAN_PASSWORD"
}Do not commit real credentials. See the GRiSP networking guide.
Ethernet is always configured. For Ethernet-only networking, omit the Wi-Fi
options; the configure task then leaves out wlan=enable, the wpa setting,
and wpa_supplicant.conf.
When --grisp-io is enabled, the generated project also includes the required
GRiSP.io dependencies and release applications. Its Logger level is set to
:notice to avoid emitting connection-level debug messages on the board.
Deploy to the configured destination:
mix grisp.deploy
mix grisp.deploy --relname my_app --relvsn 0.1.0
mix grisp.deploy --destination /Volumes/GRISP --forceIf more than one release is configured, --relname is required. Use --tar
to create _grisp/deploy/grisp2.RELNAME.RELVSN.tar.gz instead of copying to a
destination:
mix grisp.deploy --tarOptions are --relname/-n, --relvsn/-v, --tar/-t,
--destination/-d, --force/-f, --pre-script, and --post-script.
Options after -- are forwarded to mix release:
mix grisp.deploy --tar -- --quietThe task compiles with GRISP=yes and GRISP_PLATFORM set, resolves or reuses
the target OTP package, creates a Mix release with the target ERTS, and applies
all application grisp/*/deploy overlays.
The default command generates a system-partition firmware under
_grisp/firmware:
mix grisp.firmwareAvailable outputs are:
- system firmware (
.sys.gz), enabled by default and disabled with--no-system; - an eMMC image (
.emmc.gz) with--image; - bootloader firmware (
.boot.gz) with--bootloader.
Examples:
mix grisp.firmware --relname my_app --relvsn 0.1.0
mix grisp.firmware --image --bootloader --force --refresh
mix grisp.firmware --image --no-truncate
mix grisp.firmware --bundle path/to/release.tar.gzOther options are --[no-]compress, --quiet, and all release-selection
options. If no bundle is supplied, the task creates one through
grisp.deploy --tar; --refresh recreates it. Image and bootloader generation
require a toolchain.
To install firmware, copy it to the GRiSP SD card, unmount the card, open the
serial console, insert the card, reset, and interrupt barebox. Write the system
firmware to the active partition (/dev/mmc1.0 or /dev/mmc1.1):
uncompress /mnt/mmc/grisp2.RELNAME.RELVSN.sys.gz /dev/mmc1.0
Write an eMMC image or a bootloader image to /dev/mmc1:
uncompress /mnt/mmc/grisp2.RELNAME.RELVSN.emmc.gz /dev/mmc1
uncompress /mnt/mmc/grisp2.RELNAME.RELVSN.boot.gz /dev/mmc1
A truncated image contains only the first system partition. Set the active
system to 0 before booting it. Writing system firmware to the inactive A/B
partition does not change which partition the board boots.
Create _grisp/update/grisp2.RELNAME.RELVSN.tar:
mix grisp.pack
mix grisp.pack --with-bootloader
mix grisp.pack --refresh --force
mix grisp.pack --key private_key.pemThe task reuses or generates firmware automatically. Options include
--system, --bootloader, --block-size, --key, --with-bootloader,
--refresh, --force, and --quiet. If explicit firmware is used, an
explicit bootloader must be accompanied by an explicit system firmware.
For A/B updates, include grisp_updater_grisp2 and configure :grisp_updater:
config :grisp_updater,
signature_check: true,
signature_certificates: {:priv, :my_app, "certificates/updates"},
system: {:grisp_updater_grisp2, %{}},
sources: [
{:grisp_updater_tarball, %{}},
{:grisp_updater_http, %{backend: {:grisp_updater_grisp2, %{}}}}
]Extract the package under releases/RELNAME/RELVSN, serve releases over
HTTP, then update and validate from IEx:
:grisp_updater.update("http://HOST_IP:8000/RELNAME/RELVSN")
:grisp_updater.validate()When signature checking is enabled, use --key and install the corresponding
public certificate in the configured directory.
mix grisp.package list
mix grisp.package list --type toolchain
mix grisp.package list --cached
mix grisp.package list --columns version,hash,urlUse --platform to override the configured platform. OTP columns are
version, hash, name, size, etag, url, and last_modified.
Toolchain results also provide os, os_version, revision, and latest.
Custom drivers, NIFs, and GRiSP system changes require a custom OTP build. Add a toolchain to the GRiSP configuration:
defp grisp do
[
platform: :grisp2,
otp: [version: "29", jit: true],
build: [
toolchain: [
# Local installation takes precedence:
directory: "/PATH/TO/grisp2-rtems-toolchain/rtems/VERSION/"
# Or: docker: "grisp/grisp2-rtems-toolchain"
]
],
deploy: [destination: "/PATH/TO/DESTINATION"]
]
endGRISP_TOOLCHAIN overrides the configured directory. Build with:
mix grisp.build
mix grisp.build --no-configure
mix grisp.build --clean
mix grisp.build --tar
mix grisp.build --update-prebuildThe installation is stored under _grisp/otp/VERSION/install. Reconfigure
after adding C sources; --no-configure can speed up rebuilds after ordinary
source changes.
mix grisp.report
mix grisp.report --tarReports are written under _grisp/report. Review them for private information
before sharing.
To test local branches, place both repositories in the consuming project's
_checkouts directory:
git clone https://github.com/grisp/mix_grisp.git _checkouts/mix_grisp
git clone https://github.com/grisp/grisp_tools.git _checkouts/grisp_toolsMix automatically gives checkout dependencies precedence over Hex packages.
If boot fails with cannot expand $RELEASE_LIB in bootfile, ensure the
-boot_var RELEASE_LIB {{release_name}}/lib option is present. If BEAM files
were compiled for a later runtime, switch the development host to the target
OTP major and rebuild:
mix clean
mix deps.clean --all --build
mix deps.get
mix grisp.deploy