Erlang Development
Relevant source files
The following files were used as context for generating this wiki page:
Erlang development within the AtomVM ecosystem focuses on creating applications for resource-constrained IoT devices by leveraging a functional, concurrency-oriented programming model. AtomVM provides a lightweight implementation of the Bogdan Erlang Abstract Machine (BEAM), allowing code written in Erlang to execute on microcontrollers such as the ESP32 and STM32. The development workflow typically involves writing Erlang source code, compiling it to BEAM bytecode, and packaging it into AtomVM-specific "packbeam" (.avm) files for deployment.
The runtime environment supports standard Erlang features including lightweight process spawning, pre-emptive scheduling, and message passing. This architecture allows developers to handle simultaneous tasks, such as sensor reading and networking, more naturally than in traditional imperative languages like C or C++. Sources: doc/src/index.rst, doc/src/welcome-to-atomvm.md:12-25, doc/src/getting-started-guide.md:65-75.
Development Workflow and Tooling
Developing for AtomVM relies on existing Erlang toolchains. Developers use the standard Erlang compiler (erlc) or higher-level build tools like rebar3. The core difference in the AtomVM workflow is the final packaging step where BEAM files are bundled into an .avm file.
Compilation and Packaging
The following diagram illustrates the transition from Erlang source code to a deployable AtomVM application:
The packbeam tool is essential for assembling the BEAM files into a format the virtual machine can load from flash memory or the command line. Sources: doc/src/welcome-to-atomvm.md:88-95, doc/src/getting-started-guide.md:65-75.
Recommended Practices
- Coding Style: Erlang source code style is enforced using
erlfmt. Sources: CONTRIBUTING.md:115-117. - Version Control: Commit messages should follow standard OTP guidelines, and branches should be squashed and rebased before pull requests. Sources: CONTRIBUTING.md:28-35.
- Build Tools:
rebar3is the recommended tool for managing dependencies and compiling Erlang libraries such asestdlibandeavmlib. Sources: doc/CMakeLists.txt:75-80, doc/src/getting-started-guide.md:46-50.
Core Erlang Libraries
AtomVM provides a subset of the standard Erlang/OTP libraries, optimized for microcontrollers, alongside hardware-specific libraries.
| Library | Description |
|---|---|
estdlib | A lightweight version of the Erlang Standard Library. |
eavmlib | AtomVM-specific library for hardware interfacing (GPIO, I2C, SPI, UART). |
alisp | Lisp-like implementation details or extensions for AtomVM. |
etest | Testing framework for AtomVM Erlang code. |
Sources: doc/src/index.rst, doc/CMakeLists.txt:84-89.
Runtime execution and Processes
AtomVM simulates the BEAM by managing Erlang "processes" within its own memory space. These processes are not OS-level threads but lightweight units of execution managed by the AtomVM scheduler.
Process Lifecycle and Scheduling
The scheduler manages processes across different states to ensure fair execution. In SMP-enabled builds, AtomVM can run one scheduler thread per CPU core.
Processes yield execution when they reach a specific number of "reductions" or when they block on a message receive. Sources: doc/src/atomvm-internals.md:65-75, 235-245.
Mailboxes and Inter-Process Communication (IPC)
Communication is strictly via message passing. Each process has an "outer" and "inner" mailbox to allow for lock-free message enqueuing using atomic operations.
- Outer Mailbox: Where incoming messages are first placed by sender processes.
- Inner Mailbox: Where the recipient process moves messages for processing during its execution loop.
- Signals: Special messages used for system operations, such as garbage collection requests or
process_infoqueries.
Sources: doc/src/atomvm-internals.md:310-335.
JIT and Native Code Execution
For performance-critical applications, AtomVM supports Just-In-Time (JIT) compilation and Native code execution on supported architectures (x86_64, aarch64, armv6m, riscv32).
- Emulated Mode: The default mode where BEAM bytecode is interpreted.
- JIT Mode: Bytecode is translated to native machine code at runtime by the
code_server. - Native/Hybrid Mode: Code is pre-compiled on a desktop and bundled into the AVM file in a dedicated
avmNchunk.
On devices like the Raspberry Pi Pico, the JIT compiler can stream generated native code directly to flash memory for persistence across reboots. Sources: doc/src/atomvm-internals.md:175-210.
Hardware Interfacing
Erlang development for IoT involves interacting with physical peripherals. AtomVM maps Erlang function calls to native drivers for common protocols.
| Interface | Erlang Access via eavmlib |
|---|---|
| GPIO | Digital I/O pin control. |
| I2C/SPI | Synchronous serial communication for sensors and displays. |
| UART | Asynchronous serial communication. |
| Networking | WiFi and IP stack interactions (e.g., on ESP32). |
Sources: doc/src/welcome-to-atomvm.md:21-25, 45-50.
Deployment and Execution
Applications are deployed by flashing the .avm file to a specific address on the microcontroller's flash storage. On the ESP32, this is typically 0x210000 for "thin" images.
The VM searches the data partition for a module exporting a start/0 function to begin execution. Sources: doc/src/getting-started-guide.md:65-85, 125-135.
Summary
Erlang development on AtomVM brings the reliability and concurrency of the BEAM to the embedded world. By using familiar tools like rebar3 and standard Erlang syntax, developers can build complex, multi-tasking IoT applications that remain maintainable and robust under the constraints of microcontroller hardware. Sources: doc/src/welcome-to-atomvm.md:100-110.