Skip to content

Commit 589a11b

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 abe4f9c commit 589a11b

26 files changed

+1686
-0
lines changed

.github/workflows/pico-build.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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: [push, pull_request]
10+
11+
jobs:
12+
pico:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repo
16+
uses: actions/checkout@v3
17+
18+
- name: "Install deps"
19+
run: sudo apt install -y cmake gperf ninja-build gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
20+
21+
- name: Build
22+
shell: bash
23+
working-directory: ./src/platforms/rp2040/
24+
run: |
25+
set -euo pipefail
26+
mkdir build
27+
cd build
28+
cmake .. -G Ninja
29+
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: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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 on Raspberry Pico
26+
===================================
27+
28+
VM binary is file `src/platforms/rp2040/build/src/AtomVM.uf2`. Simply copy it
29+
to the pico. The VM will crash because there is no application.
30+
31+
Installing atomvm library to Raspberry Pico
32+
===========================================
33+
34+
AtomVM library must be installed as well.
35+
36+
Building it
37+
-----------
38+
39+
Build of standard libraries is part of the generic unix build.
40+
41+
From the root of the project:
42+
43+
```
44+
mkdir build
45+
cd build
46+
cmake .. -G Ninja
47+
ninja
48+
```
49+
50+
> Note: requires cmake, ninja, Erlang/OTP and Elixir for elixir libs
51+
52+
The library to install is `build/libs/atomvmlib.uf2`
53+
The VM currently expects the library to be loaded at address 0x10080000.
54+
55+
Running BEAM code on Raspberry Pico
56+
===================================
57+
58+
* BEAM module must be stripped before using PackBEAM:
59+
60+
```
61+
./PackBEAM packed.avm module.beam
62+
```
63+
64+
Then the BEAM file must be converted to UF2.
65+
The VM currently expects the application to be loaded at address 0x100A0000.
66+
67+
```sh
68+
./uf2tool create -o packed.uf2 -s 0x10080000 packed.avm
69+
```
70+
71+
Copy this UF2 to the Pico. You probably also need atomvmlib.uf2 first.
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+

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)