AtomVM Tooling
AtomVM provides an implementation of the Erlang virtual machine, and as such it provides runtime support for applications targeted for the platform.
However, developers will typically make use of downstream tooling that simplifies the development and provisioning of applications onto devices that are running the on the virtual machine.
This chapter presents an overview of these tools and how they can be used to make you more productive as an AtomVM developer.
Two tools are supported, one for Erlang developers, and one for Elixir developers:
For Erlang developers:
atomvm_rebar3_plugin
For Elixir developers:
ExAtomVM
atomvm_rebar3_plugin
The atomvm_rebar3_plugin
is a rebar3 plugin that can be used to create and flash Erlang applications that run over AtomVM. Using this plugin greatly simplifies the process of building Erlang applications that run over AtomVM, and is strongly encouraged for all users.
Prerequisites for atomvm_rebar3_plugin
To use the atomvm_rebar3_plugin
, you will need the following software on your development machine:
A suitable version of the Erlang/OTP distribution. See the Release Notes for information about supported Erlang/OTP versions.
A recent version of the rebar3 command-line tool.
(optional) The git command line tool, to follow examples in this chapter.
For flashing to ESP32, the
esptool
program.For flashing to STM32,
st-flash
via stlink(optional) A serial console program such as minicom or screen, to view console output from a device.
(recommended) For rp2040,
picotool
for software resets on Raspberry Pi Pico. (optionally used if found in PATH to disconnect activescreen
sessions, which normally prevent flashing)
Erlang Example Program
To see this plugin in action, we will clone the atomvm_examples
Github repository, and build and run the most simple
$ git clone https://github.com/atomvm/atomvm_examples
...
$ cd atomvm_examples/erlang/hello_world
From this directory we will run various rebar3 targets in the steps below.
Creating an AtomVM AVM file with rebar3
To create an AtomVM packbeam file (ending in .avm
), use the packbeam
target in the atomvm
namespace:
$ rebar3 atomvm packbeam
...
===> AVM file written to .../hello_world/_build/default/lib/hello_world.avm
See also
See the atomvm_rebar3_plugin
page for more detailed instructions
about how to use the packbeam
target.
Running applications on generic_unix
If you have installed AtomVM on a generic UNIX platform, you and run the example program directly using the atomvm
command:
$ atomvm _build/default/lib/hello_world.avm
Hello World
Return value: ok
For instructions about how to install AtomVM on the generic_unix
platform, see the Getting Started Guide
Flashing your application with rebar3
The atomvm_rebar3_plugin
supports flash targets for various device types. These targets are described in more detail below.
ESP32
To flash AtomVM AVM file to an ESP32 device, use the esp32_flash
target in the atomvm
namespace. Users will typically specify the device port and baud rate as command-line options to this target.
Important
In order to use the esp32_flash
target, you will need to install the
esptool
program.
For example:
$ rebar3 atomvm esp32_flash --port /dev/ttyUSB0 --baud 921600
...
===> esptool.py --chip auto --port /dev/ttyUSB0 --baud 921600 --before default_reset
--after hard_reset write_flash -u --flash_mode keep --flash_freq keep --flash_size detect
0x210000 atomvm_examples/erlang/hello_world/_build/default/lib/hello_world.avm
Tip
A baud rate of 921600 works well for most ESP32 devices, some can work reliably at higher rates of 1500000, or even 2000000, but some devices (especially those with a 26Mhz crystal frequency, rather than the more common 40 Mhz crystal) may need to use a slower baud rate such as 115200.
Note. A baud rate of 921600 works well for most ESP32 devices, some can work reliably at higher rates of 1500000, or even 2000000, but some devices (especially those with a 26Mhz crystal frequency, rather than the more common 40 Mhz crystal) may need to use a slower baud rate such as 115200.
See the atomvm_rebar3_plugin
page for more detailed instructions about how to use the esp32_flash
target.
You can now use a serial console program such as minicom or screen to view console output from a device.
###########################################################
### ######## ####### ## ## ## ## ## ##
## ## ## ## ## ### ### ## ## ### ###
## ## ## ## ## #### #### ## ## #### ####
## ## ## ## ## ## ### ## ## ## ## ### ##
######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ####### ## ## ### ## ##
###########################################################
I (852) AtomVM: Starting AtomVM revision 0.6.0-alpha.1
I (862) sys: Loaded BEAM partition boot.avm at address 0x1d0000 (size=262144 bytes)
I (882) network_driver: Initialized network interface
I (882) network_driver: Created default event loop
I (902) AtomVM: Found startup beam esp32init.beam
I (922) AtomVM: Starting esp32init.beam...
---
AtomVM init.
I (932) sys: Loaded BEAM partition main.avm at address 0x210000 (size=1048576
bytes)
Starting application...
Hello World
AtomVM finished with return value: ok
I (972) AtomVM: AtomVM application terminated. Going to sleep forever ...
STM32
To flash AtomVM AVM file to an STM32 device, use the stm32_flash
target in the atomvm
namespace.
Important
In order to use the stm32_flash
target, you will need to install the st-flash
tool from the open source (bsd-3
licensed)stlink suite of stm32 utilities.
Since the AtomVM core libraries are not flashed to an STM32 device, you will need to include is library in your application. As part of the build process for the STM32, you will have built the AtomVM core libraries into a file named atomvmlib.avm
Danger
It is critical that the version of the AtomVM core libraries match the version of the AtomVM virtual machine you
built as part of the STM32 build. Be sure to use the version of this library (written to build/lib/atomvmlib.avm
during the build process). For more information about how to build AtomVM for the STM32 platform, see the AtomVM
Build Instructions.
In general, it is also a good idea to use the prune option when creating your application’s AVM file. This way, only the modules that are needed for your application will be included, which will decrease the size of your application’s AVM file, leading to faster development times.
Edit the rebar.config
so that it includes the following atomvm_rebar3_plugin
stanza, if it does not already.
{atomvm_rebar3_plugin, [
{packbeam, [prune]}
]}.
This stanza will guarantee that the generated packbeam file will be pruned when created.
You will need to first build a packbeam file that includes the AtomVM core libraries. Use the packbeam
task in the atomvm
namespace, and specify the path to the atomvmlib.avm
file you created as part of the build.
$ rebar3 atomvm packbeam -e /path/to/atomvmlib.avm
You may now flash your application to your STM32 device:
$ rebar3 atomvm stm32_flash
...
===> st-flash --reset write _build/default/lib/hello_world.avm 0x8080000
For devices with only 512KB of flash the application address is different and must be specified:
$ rebar3 atomvm stm32_flash -o 0x8060000
...
===> st-flash --reset write _build/default/lib/hello_world.avm 0x8060000
See the atomvm_rebar3_plugin
page for more detailed instructions about how to use the stm32_flash
target.
You can now use a serial console program such as minicom or screen to view console output from a device.
###########################################################
### ######## ####### ## ## ## ## ## ##
## ## ## ## ## ### ### ## ## ### ###
## ## ## ## ## #### #### ## ## #### ####
## ## ## ## ## ## ### ## ## ## ## ### ##
######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ####### ## ## ### ## ##
###########################################################
INFO [51] AtomVM: Starting AtomVM revision 0.6.0-alpha.2+git.59e25c34
INFO [58] AtomVM: Booting file mapped at: 0x8080000, size: 444
INFO [64] AtomVM: Starting: hello_world.beam...
---
Hello World
INFO [74] AtomVM: Exited with return: ok
INFO [78] AtomVM: AtomVM application terminated. Going to sleep forever ...
Raspberry Pico
To generate a Raspberry Pico uf2 file from an AtomVM AVM file and flash it to an rp2040 device, use the pico_flash
target in the atomvm
namespace.
For example:
$ rebar3 atomvm pico_flash
...
===> AVM file written to _build/default/lib/hello_world.avm
===> Resetting device at path /dev/ttyACM0
===> Waiting for the device at path /run/media/${USER}/RPI-RP2 to settle and mount...
===> Copying atomvm_examples/erlang/hello_world/_build/default/lib/hello.uf2 to
/run/media/${USER}/RPI-RP2...
See the atomvm_rebar3_plugin
page for more detailed instructions about how to use the pico_flash
target.
You can now use a serial console program such as minicom or screen to view console output from a device. The default build will wait 20 seconds for a serial connection to be established before starting the application.
###########################################################
### ######## ####### ## ## ## ## ## ##
## ## ## ## ## ### ### ## ## ### ###
## ## ## ## ## #### #### ## ## #### ####
## ## ## ## ## ## ### ## ## ## ## ### ##
######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ####### ## ## ### ## ##
###########################################################
Starting AtomVM revision 0.6.0-alpha.2+git.59e25c34
Found startup beam hello_world.beam
Starting hello_world.beam...
---
Hello World
AtomVM finished with return value: ok
AtomVM application terminated. Going to sleep forever ...
If no connection is made before the timeout is reached the application will start, but the uart console will not be available. At this point you can use picotool
to reboot the device into application
mode.
Example:
$ picotool reboot -f
The device was asked to reboot into application mode.
$
This will again give you 20 seconds to establish a serial monitor connection. For information about changing this timeout, or locking down the device so that software resets no longer work (requiring that the device be power cycled and the BOOTSEL
button help when powering on to flash) consult the rp2040 section of the Build Instructions.
ExAtomVM
The ExAtomVM
tool is a mix plugin that can be used to create and flash Elixir applications that run over AtomVM. Using this plugin greatly simplifies the process of building Elixir applications that run over AtomVM, and is strongly encouraged for new users.
Prerequisites for ExAtomVM
To use the ExAtomVM
tool, you will need the following software on your development machine:
A suitable version of the Erlang/OTP distribution. See the Release Notes for information about supported Erlang/OTP versions.
A suitable version of the Elixir distribution. See the Release Notes for information about supported Elixir versions.
(optional) The git command line tool, to follow examples in this chapter.
For flashing to ESP32, the
esptool
program.(optional) A serial console program such as minicom or screen, to view console output from a device.
Elixir Example Program
To see this plugin in action, we will clone the atomvm_examples
Github repository, and build and run the most simple
$ git clone https://github.com/atomvm/atomvm_examples
...
$ cd atomvm_examples/elixir/HelloWorld
From this directory we will run various mix
targets in the steps below.
Creating an AtomVM AVM file with mix
To create an AtomVM packbeam file (ending in .avm
), first use the mix.deps
target to mix in order to download any dependencies:
$ mix deps.get
* Updating exatomvm (https://github.com/atomvm/ExAtomVM/)
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 17 (delta 6), reused 16 (delta 6), pack-reused 0
origin/HEAD set to main
You can now use the atomvm.packbeam
target to create a packbeam (ending in .avm
) file:
$ mix atomvm.packbeam
==> exatomvm
Compiling 5 files (.ex)
Generated exatomvm app
==> HelloWorld
Compiling 1 file (.ex)
Generated HelloWorld app
No avm_deps directory found.
This message can be safely ignored when standard libraries are already flashed to lib
partition.
The HelloWorld.avm
is located in the top level directory:
$ ls -l HelloWorld.avm
-rw-rw-r-- 1 user wheel 19120 Oct 13 14:06 HelloWorld.avm
See also
See the ExAtomVM
page for more detailed instructions about how to use the
atomvm.packbeam
target.
Running on the generic_unix
platform
If you have installed AtomVM on a generic UNIX platform, you and run the example program directly using the atomvm
command:
$ atomvm HelloWorld.avm
Hello World
Return value: ok
For instructions about how to install AtomVM on the generic_unix
platform, see the Getting Started Guide
Flashing your application with mix
The ExAtomVM
plugin supports flash targets for various device types. These targets are described in more detail below.
Attention
Currently, the ExAtomVM
tool only supports flash targets for the ESP32 and
STM32 platforms.
ESP32 flash task
To flash AtomVM packbeam file to an ESP32 device, use the mix.esp32.flash
target. Users will typically specify the device port and baud rate as command-line options to this target.
Important
In order to use the mix.esp32.flash
target, you will need to install the esptool
program.
For example:
$ mix atomvm.esp32.flash --port /dev/ttyUSB0 --baud 921600
Tip
A baud rate of 921600 works well for most ESP32 devices, some can work reliably at higher rates of 1500000, or even 2000000, but some devices (especially those with a 26Mhz crystal frequency, rather than the more common 40 Mhz crystal) may need to use a slower baud rate such as 115200.
Note. A baud rate of 921600 works well for most ESP32 devices, some can work reliably at higher rates of 1500000, or even 2000000, but some devices (especially those with a 26Mhz crystal frequency, rather than the more common 40 Mhz crystal) may need to use a slower baud rate such as 115200.
See the ExAtomVM
page for more detailed instructions about how to use the mix.esp32.flash
target.
You can now use a serial console program such as minicom or screen to view console output from a device.
###########################################################
### ######## ####### ## ## ## ## ## ##
## ## ## ## ## ### ### ## ## ### ###
## ## ## ## ## #### #### ## ## #### ####
## ## ## ## ## ## ### ## ## ## ## ### ##
######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ####### ## ## ### ## ##
###########################################################
I (852) AtomVM: Starting AtomVM revision 0.6.0-alpha.1
I (862) sys: Loaded BEAM partition boot.avm at address 0x1d0000 (size=262144 bytes)
I (882) network_driver: Initialized network interface
I (882) network_driver: Created default event loop
I (902) AtomVM: Found startup beam esp32init.beam
W (902) sys: AVM partition not found for lib.avm
I (902) AtomVM: Unable to mount lib.avm partition. Hopefully the AtomVM core libraries
are included in your application.
I (922) AtomVM: Starting esp32init.beam...
---
AtomVM init.
I (932) sys: Loaded BEAM partition main.avm at address 0x210000 (size=1048576 bytes)
Starting application...
Hello World
AtomVM finished with return value: ok
I (972) AtomVM: AtomVM application terminated. Going to sleep forever ...
STM32 flash task
To flash AtomVM packbeam file to an STM32 device, use the atomvm.stm32.flash
mix target.
Important
In order to use the mix.stm32.flash
target, you will need to install the st-flash
tool from the open source
(bsd-3 licensed) stlink suite of stm32 utilities.
For example:
$ mix atomvm.stm32.flash
Most devices do not need to enter the default application offset 0x8080000
, but devices with only 512KiB of flash storage need to use --flash_offset=0x8060000
parameter setting to upload the application to the correct flash location.
BlackPill V2 example:
$ mix atomvm.stm32.flash --flash_offset=0x8060000
If the st-flash
tool is not in environment PATH, the full path to the st-flash
tool should be exported to the environment variable ATOMVM_MIX_PLUGIN_STFLASH
, for example:
$ export ATOMVM_MIX_PLUGIN_STFLASH=/opt/stlink/bin/st-flash
atomvm_packbeam
The atomvm_packbeam tool is a simple command-line utility that allows you to create, inspect, and manipulate AtomVM PackBEAM files. By convention, PackBEAM files end in the .avm
suffix and are referred to as “AVM” files, in the remainder of this section.
Tip
Users generally do not have a need to use the packbeam
tool directly. Instead, the functionality of this tool is
embedded in the atomvm_rebar3_plugin
.
Installation
Consult the atomvm_packbeam Github page for instructions about how to install the atomvm_packbeam
utility. Once installed, you should have the packbeam
command line tool available in your PATH
.
Usage
The packbeam
command supports the following sub-commands:
create
Create an AVM file from a collection of files.list
List the contents of an AVM file.extract
Extract elements from an AVM file.delete
Delete elements from an AVM file.
These sub-commands are described in more detail below.
See also
These notes provide only a high-level view of this packbeam
utility. For more detailed information, see the
atomvm_packbeam Github repository.
Creating AVM files
To create an AVM from a list of existing files (typically .beam
files), use the create
subcommand. Specify the output .avm
first, followed by a list of files you would like to include in the output file. E.g.,
$ packbeam create output.avm foo.beam bar.beam
Tip
Creation of AVM files is more typically done via the
atomvm_rebar3_plugin; however, the packbeam
command can be used
to inspect and/or manipulate AVM files after they have been created by this plugin. This isn’t typically required,
but in some instances it can be useful.
Note that you can supply a previously created AVM file as an input to another creation, which will result in including all the files in the source AVM file in the destination.
$ packbeam create new_output.avm tapas.beam output.avm
You can also embed non-BEAM files in an AVM file. These files are accessible programmatically withing atomvm via the atomvm:read_priv/2
function, described in the AtomVM Programmer’s Guide.
For example, if you wanted to add a file my_app/priv/my_file.txt
to a new file, you could use the following command:
$ packbeam create my_app.beam my_app/priv/my_file.txt my_lib.avm
Important
There are conventions for embedding non-BEAM files in AVM files that need to be followed in order to be able to
load these files programmatically within AtomVM. Generally, these files must obey the path
<module-name>/priv/<path-to-file>
, where <module-name>
is the name of a module, and <path-to-file>
is a path
to the embedded file. (This path may include embedded /
separators). Example: my_app/priv/bubbles/sample.txt
Start Flags
An AtomVM application must contain a start entrypoint, i.e., a module that exports the start/0
function. You can specify the name of this module via the --start
flag. E.g.,
$ packbeam create --start main my_app.avm foo.beam bar.beam main.beam
Use of this flag will ensure that the main.beam
module will be found first in the search order when the AtomVM virtual machine starts your application.
Pruning
Pruning an AVM file is a useful mechanism for making your AVM files smaller, and thus faster to flash and including less data than necessary. You can prune an AVM using the
$ packbeam create --start main --prune my_app.beam foo.beam bar.beam main.beam a.beam \
b.beam c.beam
Any BEAM files that contain no transitive references from the start module are removed from the output AVM file, making them smaller and less bloated.
Important
You can only use the --prune
option if you specify a --start
module.
Listing AVM file contents
You can list the contents of an AVM file via the list
sub-command.
$ packbeam list myapp.avm
myapp.beam * [384]
myapp/priv/application.bin [220]
Any BEAM files with an exported start/0
function are listed with an asterisk (*
). In general, if you want your application to start from a designated entrypoint, that BEAM file should occur first in the list.
The size (in bytes) of the entries are listed in square brackets ([]
).
Extracting AVM file contents
You can extract elements of an AVM file, writing them to the file system, using the extract
sub-command.
Specify the directory location into which you would like to extract the files using the -out
flag, followed by the path to the input AVM file, and a list of paths from the input AVM you would like to extract.
$ mkdir mydir
$ packbeam extract -out mydir myapp.avm myapp/priv/application.bin
Writing to mydir ...
x myapp/priv/application.bin
Deleting AVM file contents
You can delete elements of an AVM file using the delete
sub-command.
Specify the AVM file you would like to write as output (which can be the same as the input AVM file) using the -out
flag, followed by the path to the input AVM file, and a list of paths from the input AVM you would like to delete.
$ packbeam delete -out myapp2.avm myapp.avm myapp/priv/application.bin
shell$ packbeam list myapp2.avm
myapp.beam * [384]
Help
To get help about packbeam
syntax, use the help
subcommand:
$ packbeam help
packbeam version 0.7.0
Syntax:
packbeam <sub-command> <options> <args>
The following sub-commands are supported:
create <options> <output-avm-file> [<input-file>]+
where:
<output-avm-file> is the output AVM file,
[<input-file>]+ is a list of one or more input files,
and <options> are among the following:
[--prune|-p] Prune dependencies
[--start|-s <module>] Start module
[--remove_lines|-r] Remove line number information from AVM files
list <options> <avm-file>
where:
<avm-file> is an AVM file,
and <options> are among the following:
[--format|-f csv|bare|default] Format output
extract <options> <avm-file> [<element>]*
where:
<avm-file> is an AVM file,
[<element>]+ is a list of one or more elements to extract
(if empty, then extract all elements)
and <options> are among the following:
[--out|-o <output-directory>] Output directory into which to write elements
(if unspecified, use the current working directory)
delete <options> <avm-file> [<element>]+
where:
<avm-file> is an AVM file,
[<element>]+ is a list of one or more elements to delete,
and <options> are among the following:
[--out|-o <output-avm-file>] Output AVM file
version
Print version and exit
help
Print this help
See also
For more detailed information about the atomvm_packbeam
utility, see
the atomvm_packbeam documentation Github page.
Where to go from here
With knowledge of AtomVM tooling, you can more easily follow the AtomVM Example Programs, or read the Programmers Guide and start writing your own applications.