Skip to content

Commit 620e503

Browse files
committed
Initial support for Raspberry Pico
Also slightly modify SMP code to handle the specific case of the Pico. Code relies on condition variables implementation proposed in this upstream PR: raspberrypi/pico-sdk#1101 Signed-off-by: Paul Guyot <[email protected]>
1 parent c8bf97f commit 620e503

26 files changed

+1734
-0
lines changed

.github/workflows/pico-build.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#
2+
# Copyright 2022 Paul Guyot <[email protected]>
3+
#
4+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
#
6+
7+
name: Pico Build
8+
9+
on:
10+
push:
11+
paths:
12+
- '.github/workflows/**'
13+
- 'CMakeLists.txt'
14+
- 'libs/**'
15+
- 'src/platforms/rp2040/**'
16+
- 'src/libAtomVM/**'
17+
pull_request:
18+
paths:
19+
- '.github/workflows/**'
20+
- 'CMakeLists.txt'
21+
- 'libs/**'
22+
- 'src/platforms/rp2040/**'
23+
- 'src/libAtomVM/**'
24+
25+
26+
jobs:
27+
pico:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout repo
31+
uses: actions/checkout@v3
32+
33+
- name: "Install deps"
34+
run: sudo apt install -y cmake gperf ninja-build gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
35+
36+
- name: Build
37+
shell: bash
38+
working-directory: ./src/platforms/rp2040/
39+
run: |
40+
set -euo pipefail
41+
mkdir build
42+
cd build
43+
cmake .. -G Ninja
44+
ninja

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ endif()
4343

4444
add_subdirectory(tests)
4545
add_subdirectory(tools/packbeam)
46+
add_subdirectory(tools/uf2tool)
47+
4648
if (NOT "${CMAKE_GENERATOR}" MATCHES "Xcode")
4749
add_subdirectory(libs)
4850
add_subdirectory(examples)

CMakeModules/BuildErlang.cmake

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ macro(pack_lib avm_name)
8383
add_dependencies(${avm_name} ${avm_name}_main)
8484
endif()
8585

86+
add_custom_target(
87+
${avm_name}.uf2 ALL
88+
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x10080000 ${avm_name}.avm
89+
COMMENT "Creating UF2 file ${avm_name}.uf2"
90+
VERBATIM
91+
)
92+
add_dependencies(${avm_name}.uf2 ${avm_name})
93+
8694
endmacro()
8795

8896

@@ -153,3 +161,45 @@ macro(pack_test test_avm_name)
153161
add_dependencies(${test_avm_name} ${ARCHIVE_TARGETS} PackBEAM)
154162

155163
endmacro()
164+
165+
macro(pack_uf2 avm_name main)
166+
167+
add_custom_command(
168+
OUTPUT ${main}.beam
169+
COMMAND erlc -I ${CMAKE_SOURCE_DIR}/libs/include ${CMAKE_CURRENT_SOURCE_DIR}/${main}.erl
170+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${main}.erl
171+
COMMENT "Compiling ${main}.erl"
172+
VERBATIM
173+
)
174+
175+
add_custom_target(
176+
${avm_name}_main
177+
DEPENDS ${main}.beam
178+
)
179+
180+
foreach(archive_name ${ARGN})
181+
if(NOT ${archive_name} STREQUAL "exavmlib")
182+
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/src/${archive_name}.avm)
183+
else()
184+
set(ARCHIVES ${ARCHIVES} ${CMAKE_BINARY_DIR}/libs/${archive_name}/lib/${archive_name}.avm)
185+
endif()
186+
set(ARCHIVE_TARGETS ${ARCHIVE_TARGETS} ${archive_name})
187+
endforeach()
188+
189+
add_custom_target(
190+
${avm_name}.avm ALL
191+
COMMAND ${CMAKE_BINARY_DIR}/tools/packbeam/PackBEAM ${avm_name}.avm ${main}.beam ${ARCHIVES}
192+
COMMENT "Packing runnable ${avm_name}.avm"
193+
VERBATIM
194+
)
195+
add_dependencies(${avm_name}.avm ${avm_name}_main ${ARCHIVE_TARGETS} PackBEAM)
196+
197+
add_custom_target(
198+
${avm_name}.uf2 ALL
199+
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x100A0000 ${avm_name}.avm
200+
COMMENT "Creating UF2 file ${avm_name}.uf2"
201+
VERBATIM
202+
)
203+
add_dependencies(${avm_name}.uf2 ${avm_name}.avm uf2tool)
204+
205+
endmacro()

README.Md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Supported Platforms
1818
* Linux, macOS, FreeBSD ([generic unix](src/platforms/generic_unix))
1919
* ESP32 SoC (with IDF/FreeRTOS, see [README.ESP32.Md](README.ESP32.Md))
2020
* STM32 MCUs (with LibOpenCM3, see [README.STM32.Md](README.STM32.Md))
21+
* Raspberry Pi Pico (see [README.PICO.Md](README.PICO.Md))
2122

2223
AtomVM aims to be easily portable to new platforms with a minimum effort, so additional platforms
2324
might be supported in a near future.

README.PICO.Md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<!--
2+
Copyright 2022 Paul Guyot <[email protected]>
3+
4+
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
-->
6+
7+
Building AtomVM for Raspberry Pico
8+
==================================
9+
10+
* build:
11+
12+
```
13+
cd src/platforms/rp2040/
14+
mkdir build
15+
cd build
16+
cmake .. -G Ninja
17+
ninja
18+
```
19+
20+
> Note: requires cmake and ninja
21+
22+
You may want to build with option `AVM_REBOOT_ON_NOT_OK` so Pico restarts on
23+
error.
24+
25+
Installing AtomVM and programs on Raspberry Pico
26+
================================================
27+
28+
The approach consists in installing various uf2 files which include the
29+
address they should be loaded to.
30+
31+
You typically need three uf2 files:
32+
- `AtomVM.uf2` for the VM
33+
- `atomvmlib.uf2` for the standard libraries
34+
- your application's uf2.
35+
36+
We provide an escript-based (what else?) tool to build uf2 files called
37+
`uf2tool` that you can use to bundle your `avm` into uf2.
38+
39+
If you need to upgrade AtomVM or the standard libraries, simply copy them again.
40+
41+
Installing AtomVM on Raspberry Pico
42+
===================================
43+
44+
VM binary is file `src/platforms/rp2040/build/src/AtomVM.uf2`. Simply copy it
45+
to the pico. The VM will crash because there is no application.
46+
47+
Installing atomvm library to Raspberry Pico
48+
===========================================
49+
50+
AtomVM library must be installed as well.
51+
52+
Building it
53+
-----------
54+
55+
Build of standard libraries is part of the generic unix build.
56+
57+
From the root of the project:
58+
59+
```
60+
mkdir build
61+
cd build
62+
cmake .. -G Ninja
63+
ninja
64+
```
65+
66+
> Note: requires cmake, ninja, Erlang/OTP and Elixir for elixir libs
67+
68+
Installing it
69+
-------------
70+
71+
The library to install is `build/libs/atomvmlib.uf2`
72+
73+
Running Hello Pico
74+
==================
75+
76+
This example will print a Hello Pico message repeatedly.
77+
78+
It is built into `build/examples/erlang/rp2040/hello_pico.uf2`.
79+
80+
You can install it and then connect to the serial port with minicom.
81+
82+
Running your own BEAM code on Raspberry Pico
83+
============================================
84+
85+
You need to create an avm file using PackBEAM binary (or rebar3 plugin).
86+
87+
```
88+
./PackBEAM packed.avm module.beam
89+
```
90+
91+
Then the BEAM file must be converted to UF2.
92+
The VM currently expects the application to be loaded at address 0x100A0000.
93+
94+
```sh
95+
./uf2tool create -o packed.uf2 -s 0x100A0000 packed.avm
96+
```
97+
98+
Copy this UF2 to the Pico after you copied the VM (`AtomVM.uf2`) and the
99+
standard libraries (`atomvmlib.uf2`).

examples/erlang/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ project(examples_erlang)
2323
include(BuildErlang)
2424

2525
add_subdirectory(esp32)
26+
add_subdirectory(rp2040)
2627

2728
pack_runnable(hello_world hello_world eavmlib)
2829
pack_runnable(udp_server udp_server estdlib eavmlib)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#
2+
# This file is part of AtomVM.
3+
#
4+
# Copyright 2022 Paul Guyot <[email protected]>
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
#
20+
21+
project(examples_erlang_rp2040)
22+
23+
include(BuildErlang)
24+
25+
pack_uf2(hello_pico hello_pico eavmlib estdlib)
26+
pack_uf2(pico_rtc pico_rtc eavmlib estdlib)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2022 Paul Guyot <[email protected]>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
21+
-module(hello_pico).
22+
-export([start/0]).
23+
24+
start() ->
25+
% Pico's serial may be too fast to use hello_world example, so this
26+
% version loops.
27+
hello_pico_loop().
28+
29+
hello_pico_loop() ->
30+
console:puts("Hello Pico\n"),
31+
receive
32+
ok -> ok
33+
after 3000 -> ok
34+
end,
35+
hello_pico_loop().
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2022 Paul Guyot <[email protected]>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
21+
% This example demonstrates the usage of the Pico's hardware RTC.
22+
23+
-module(pico_rtc).
24+
-export([start/0]).
25+
26+
-define(START_DATE, {{2022, 11, 16}, {22, 09, 00}}).
27+
28+
start() ->
29+
case atomvm:platform() of
30+
pico ->
31+
pico_rtc_loop();
32+
Other ->
33+
erlang:display({unexpected, Other})
34+
end.
35+
36+
pico_rtc_loop() ->
37+
Date = erlang:universaltime(),
38+
print_date(Date),
39+
receive
40+
ok -> ok
41+
after 5000 -> ok
42+
end,
43+
if
44+
Date < ?START_DATE ->
45+
pico:rtc_set_datetime(?START_DATE);
46+
true ->
47+
ok
48+
end,
49+
pico_rtc_loop().
50+
51+
print_date({{Year, Month, Day}, {Hour, Min, Sec}}) ->
52+
% Only ~p and ~s seem to exist for now.
53+
YearStr = integer_to_list(Year),
54+
MonthStr = format_2_digits(Month),
55+
DayStr = format_2_digits(Day),
56+
HourStr = format_2_digits(Hour),
57+
MinStr = format_2_digits(Min),
58+
SecStr = format_2_digits(Sec),
59+
console:puts(
60+
lists:flatten([
61+
YearStr, "-", MonthStr, "-", DayStr, "T", HourStr, ":", MinStr, ":", SecStr, "\n"
62+
])
63+
).
64+
65+
format_2_digits(Num) when Num < 10 ->
66+
["0", integer_to_list(Num)];
67+
format_2_digits(Num) ->
68+
integer_to_list(Num).

libs/eavmlib/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ set(ERLANG_MODULES
3434
logger
3535
network
3636
network_fsm
37+
pico
3738
port
3839
spi
3940
timer_manager

0 commit comments

Comments
 (0)