ExAtomVM の README をなぞって AtomVM 向け Elixir Project を作ります。
前提
mise list --current
Tool Version Source Requested
elixir 1.17.3-otp-27 ~/.config/mise/config.toml 1.17.3-otp-27
erlang 27.3.4.15 ~/.config/mise/config.toml 27.3.4.15
プロジェクト作成
$ mix new my_atomvm_project
...
$ cd my_atomvm_project
mix.exs と lib/my_atomvm_project を以下のように編集します。
--- a/mix.exs
+++ b/mix.exs
@@ -7,22 +7,24 @@ defmodule MyAtomvmProject.MixProject do
version: "0.1.0",
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
- deps: deps()
+ deps: deps(),
+ atomvm: [
+ start: MyAtomvmProject,
+ flash_offset: 0x250000
+ ]
]
end
- # Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
- # Run "mix help deps" to learn about dependencies.
defp deps do
[
- # {:dep_from_hexpm, "~> 0.3.0"},
- # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
+ {:exatomvm,
+ git: "https://github.com/atomvm/ExAtomVM/", ref: "ff7daf7e83a4e86fbf078730b6c49045a99de9f8"}
]
end
end
※ exatomvm は ref で執筆時点の最新コミットに固定しました。
--- a/lib/my_atomvm_project.ex
+++ b/lib/my_atomvm_project.ex
@@ -1,18 +1,5 @@
defmodule MyAtomvmProject do
- @moduledoc """
- Documentation for `MyAtomvmProject`.
- """
-
- @doc """
- Hello world.
-
- ## Examples
-
- iex> MyAtomvmProject.hello()
- :world
-
- """
- def hello do
- :world
+ def start do
+ :ok
end
end
$ mix deps.get
...
して、 avm_deps に AtomVM を Generic UNIX 向けにビルドして動かす でビルドした AtomVM-libs をコピーします。
$ mkdir avm_deps
$ cp /home/pojiro/Sandbox/AtomVM/build/libs/atomvmlib.avm avm_deps/
$ cp /home/pojiro/Sandbox/AtomVM/build/libs/eavmlib/src/eavmlib.avm avm_deps/
$ cp /home/pojiro/Sandbox/AtomVM/build/libs/estdlib/src/estdlib.avm avm_deps/
$ cp /home/pojiro/Sandbox/AtomVM/build/libs/exavmlib/lib/exavmlib.avm avm_deps/
それぞれソースを copilot に調べさせると以下とのことでした。
- atomvmlib.avm: AtomVMの「コアライブラリ集約版」です。
- アプリ本体のAVMとは別に指定して実行することを前提としたライブラリです。
- estdlib.avm: AtomVM向けのErlang標準ライブラリ群です。
- lists、gen_server、io、file、timer などの基礎モジュールを提供します。
- eavmlib.avm: AtomVM固有APIのライブラリです。
- ハードウェア/VM寄りの機能(GPIO/I2C/SPI/UART、console、timer_manager など)を提供します。
- exavmlib.avm: AtomVM向けのElixir側コアライブラリ群です。
- Elixirの基本モジュール群とJSON関連モジュールをまとめたライブラリです。
不要そうな以下は省いています。
- alisp.avm: Lisp実行機能ライブラリ
- etest.avm: テスト実行・アサート機能ライブラリ
avm の作成
$ mix atomvm.packbeam
...
$ ls -lah my_atomvm_project.avm
-rw-rw-r-- 1 pojiro pojiro 1003K 8月 3 17:59 my_atomvm_project.avm
Generic UNIX で実行してみる
AtomVM を Generic UNIX 向けにビルドして動かす でビルドした AtomVM で実行してみます。
$ /home/pojiro/Sandbox/AtomVM/build/src/AtomVM my_atomvm_project.avm
Return value: ok
動きました。
--- a/lib/my_atomvm_project.ex
+++ b/lib/my_atomvm_project.ex
@@ -1,5 +1,11 @@
defmodule MyAtomvmProject do
- def start do
- :ok
+ # this compiler option is to suppress warnings when compiling the VM
+ # it is not needed or recommended for user apps.
+ @compile {:no_warn_undefined, [Console]}
+ def start() do
+ Console.print("Hello World\n")
+ Console.puts("Console.puts() and Console.print() work with binary ")
+ Console.puts(~c"or charlist strings.\n")
+ Console.flush()
end
end
として、もう一度実行します。
$ /home/pojiro/Sandbox/AtomVM/build/src/AtomVM my_atomvm_project.avm
Hello World
Console.puts() and Console.print() work with binary or charlist strings.
Return value: ok
バッチリですね。M5STACK CORE S3 で動かせるでしょうか?
CORE S3 で実行してみる
$ mix atomvm.esp32.flash --port /dev/ttyACM0
Flashing using esptool..
** (ErlangError) Erlang error: :enoent
(elixir 1.18.3) lib/system.ex:1114: System.cmd("esptool.py", ["--port", "/dev/ttyACM0", "--chip", "auto", "--baud", "115200", "--before", "default_reset", "--after", "hard_reset", "write_flash", "-u", "--flash_mode", "keep", "--flash_freq", "keep", "--flash_size", "detect", "0x250000", "my_atomvm_project.avm"], [stderr_to_stdout: true, into: %IO.Stream{device: :standard_io, raw: false, line_or_bytes: 1}])
(mix 1.18.3) lib/mix/task.ex:495: anonymous fn/3 in Mix.Task.run_task/5
(mix 1.18.3) lib/mix/cli.ex:107: Mix.CLI.run_task/2
/home/pojiro/.local/share/mise/installs/elixir/1.18.3-otp-27/bin/mix:2: (file)
なるほど、であればパスを通して
source "/home/pojiro/.espressif/tools/activate_idf_v5.5.5.sh"
...
$ mix atomvm.esp32.flash --port /dev/ttyACM0
Flashing using esptool..
esptool.py v4.12.0
Serial port /dev/ttyACM0
Connecting....
Detecting chip type... ESP32-S3
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
USB mode: USB-Serial/JTAG
MAC: 48:27:e2:66:d1:10
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 16MB
Flash will be erased from 0x00250000 to 0x0034afff...
Writing at 0x00250000... (1 %)
...
Writing at 0x00348000... (100 %)
Wrote 1032192 bytes at 0x00250000 in 8.9 seconds (930.2 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
かけたっぽいです。
$ screen /dev/ttyACM0 115200
ffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
invalid header: 0xffffffff
...
ありゃりゃ。と思いましたが、 CORE S3 に AtomVM を書き込んだ覚えがありません。
flash_offset: 0x250000 を mix.exs に書きましたが、これは ESP32 Deployment Overview をみると以下のように書いてあります。次は ESP32 向けの AtomVM をビルドして書き込む必要がありそうです。
| |
+---------------+ ----------- 0x0 | 0x1000 | 0x2000 (varies by esp32 flavor)
| boot loader | ^
+---------------+ |
| partition map | | AtomVM
+---------------+ | binary
| | | image
| AtomVM | |
| Virtual | |
| Machine | |
| | v
+---------------+ ----------- 0x250000
| | ^
| | |
| data | | Erlang/Elixir
| partition | | Application
| | |
| | v
+---------------+ ----------- end
今日はここまで。
追記1
AtomVM を ESP32S3 向けにビルドして動かす でビルドしたAtomVMをM5STACK CORE S3を書き込むことで上述のコードの動作確認ができました。
追記2
以下のような mix タスクの alias を作ると便利です。 mix flash を実行するとパックと書き込みの両方が行われます。
--- a/mix.exs
+++ b/mix.exs
@@ -11,7 +11,8 @@ defmodule MyAtomvmProject.MixProject do
atomvm: [
start: MyAtomvmProject,
flash_offset: 0x250000
- ]
+ ],
+ aliases: aliases()
]
end
@@ -27,4 +28,13 @@ defmodule MyAtomvmProject.MixProject do
git: "https://github.com/atomvm/ExAtomVM/", ref: "ff7daf7e83a4e86fbf078730b6c49045a99de9f8"}
]
end
+
+ defp aliases do
+ [
+ flash: [
+ "atomvm.packbeam",
+ "atomvm.esp32.flash --port /dev/ttyACM0 --baud 921600"
+ ]
+ ]
+ end
end