Skip to content

Commit

Permalink
Add initial support for Pico-W
Browse files Browse the repository at this point in the history
Document how to build a Pico-W AtomVM binary
Also bump the load address of applications as the binary is larger

Signed-off-by: Paul Guyot <[email protected]>
  • Loading branch information
pguyot committed Oct 5, 2023
1 parent 4564ebd commit 0e0f38f
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 17 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/pico-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ concurrency:
jobs:
pico:
runs-on: ubuntu-latest
strategy:
matrix:
board: ["pico", "pico_w"]

steps:
- name: Checkout repo
uses: actions/checkout@v3
Expand All @@ -43,7 +47,7 @@ jobs:
set -euo pipefail
mkdir build
cd build
cmake .. -G Ninja
cmake .. -G Ninja -DPICO_BOARD=${{ matrix.board }}
ninja
- name: Install nvm and nodejs 20
Expand All @@ -56,6 +60,8 @@ jobs:
- name: Run tests with rp2040js
shell: bash
working-directory: ./src/platforms/rp2040/tests
# Unfortunately, rp2040js doesn't support cyw43 and cyw43_arch_init panics
if: success() && matrix.board != "pico_w"
run: |
set -euo pipefail
source $HOME/.nvm/nvm.sh
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `crypto:crypto_one_time/4,5` on ESP32
- Improved nif and port support on STM32
- Added support for `atomvm:posix_clock_settime/2`
- Added support initial for Pico-W with the on-board LED

### Fixed

Expand All @@ -30,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a bug in the STM32 port that caused the final result to never be returned.
- Fix bug when building a binary using a 64-bit integer on a 32-bit CPU.

### Breaking changes
- Pico applications now need to be located at 0x10100000 (instead of 0x100A0000).
Users need to update the parameters passed to uf2tool.

## [0.6.0-alpha.0] - 2023-08-13

### Added
Expand Down
4 changes: 2 additions & 2 deletions CMakeModules/BuildErlang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ macro(pack_lib avm_name)

add_custom_target(
${avm_name}.uf2 ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x10080000 ${avm_name}.avm
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x10100000 ${avm_name}.avm
COMMENT "Creating UF2 file ${avm_name}.uf2"
VERBATIM
)
Expand Down Expand Up @@ -208,7 +208,7 @@ macro(pack_uf2 avm_name main)

add_custom_target(
${avm_name}.uf2 ALL
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x100A0000 ${avm_name}.avm
COMMAND ${CMAKE_BINARY_DIR}/tools/uf2tool/uf2tool create -o ${avm_name}.uf2 -s 0x10180000 ${avm_name}.avm
COMMENT "Creating UF2 file ${avm_name}.uf2"
VERBATIM
)
Expand Down
18 changes: 16 additions & 2 deletions README.PICO.Md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ ninja
You may want to build with option `AVM_REBOOT_ON_NOT_OK` so Pico restarts on
error.


Building AtomVM for Raspberry Pico-W
==================================

To build for Pico-W, pass the board to cmake as follows:

```
cd src/platforms/rp2040/
mkdir build
cd build
cmake .. -G Ninja -DPICO_BOARD=pico_w
ninja
```

Installing AtomVM and programs on Raspberry Pico
================================================

Expand Down Expand Up @@ -89,10 +103,10 @@ You need to create an avm file using PackBEAM binary (or rebar3 plugin).
```

Then the BEAM file must be converted to UF2.
The VM currently expects the application to be loaded at address 0x100A0000.
The VM currently expects the application to be loaded at address 0x10100000.

```sh
./uf2tool create -o packed.uf2 -s 0x100A0000 packed.avm
./uf2tool create -o packed.uf2 -s 0x10100000 packed.avm
```

Copy this UF2 to the Pico after you copied the VM (`AtomVM.uf2`) and the
Expand Down
12 changes: 11 additions & 1 deletion doc/src/build-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ is 8N1 with no flow control.
* `Erlang/OTP`
* `Elixir` (optional)

### AtomVM build steps
### AtomVM build steps (Pico)

cd src/platforms/rp2040/
mkdir build
Expand All @@ -570,6 +570,16 @@ is 8N1 with no flow control.

> You may want to build with option `AVM_REBOOT_ON_NOT_OK` so Pico restarts on error.
### AtomVM build steps (Pico-W)

cd src/platforms/rp2040/
mkdir build
cd build
cmake .. -G Ninja -DPICO_BOARD=pico_w
ninja

> You may want to build with option `AVM_REBOOT_ON_NOT_OK` so Pico restarts on error.
### libAtomVM build steps

Build of standard libraries is part of the generic unix build.
Expand Down
4 changes: 2 additions & 2 deletions doc/src/getting-started-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ or
rebar3 packbeam -p -i packed.avm module.beam

Then the BEAM file must be converted to UF2.
The VM currently expects the application to be loaded at address 0x100A0000.
The VM currently expects the application to be loaded at address 0x10100000.

./uf2tool create -o packed.uf2 -s 0x100A0000 packed.avm
./uf2tool create -o packed.uf2 -s 0x10100000 packed.avm

Copy this UF2 to the Pico after you copied the VM (`AtomVM.uf2`) and the
standard libraries (`atomvmlib.uf2`).
Expand Down
1 change: 1 addition & 0 deletions examples/erlang/rp2040/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ include(BuildErlang)
pack_uf2(hello_pico hello_pico eavmlib estdlib)
pack_uf2(pico_blink pico_blink eavmlib estdlib)
pack_uf2(pico_rtc pico_rtc eavmlib estdlib)
pack_uf2(picow_blink picow_blink eavmlib estdlib)
3 changes: 2 additions & 1 deletion examples/erlang/rp2040/pico_blink.erl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
-module(pico_blink).
-export([start/0]).

% 25 is on-board led on Pico & Pico-W
% 25 is on-board led on Pico
% This code will not work on Pico-W where GPIO 25 has another purpose.
-define(GPIO_NUM, 25).

start() ->
Expand Down
34 changes: 34 additions & 0 deletions examples/erlang/rp2040/picow_blink.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
%
% This file is part of AtomVM.
%
% Copyright 2023 Paul Guyot <[email protected]>
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
%

-module(picow_blink).
-export([start/0]).

% 0 is CYW43 GPIO for on-board led
% This code will not work on Pico
-define(GPIO_NUM, 0).

start() ->
loop(0).

loop(N) ->
pico:cyw43_arch_gpio_put(?GPIO_NUM, N),
timer:sleep(1000),
loop((N + 1) rem 2).
28 changes: 27 additions & 1 deletion libs/eavmlib/src/pico.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
-module(pico).

-export([
rtc_set_datetime/1
rtc_set_datetime/1,
cyw43_arch_gpio_get/1,
cyw43_arch_gpio_put/2
]).

%%-----------------------------------------------------------------------------
Expand All @@ -38,3 +40,27 @@
-spec rtc_set_datetime(calendar:datetime()) -> ok.
rtc_set_datetime(_Datetime) ->
erlang:nif_error(undefined).


%%-----------------------------------------------------------------------------
%% @param GPIO pin to read
%% @returns the level of the GPIO pin
%% @doc Read a GPIO of the CYW43.
%% This function is only available on Pico-W.
%% @end
%%-----------------------------------------------------------------------------
-spec cyw43_arch_gpio_get(GPIO :: 0..2) -> 0..1.
cyw43_arch_gpio_get(_GPIO) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param GPIO pin to write
%% @param Level value to write
%% @doc Write a GPIO of the CYW43.
%% This function is only available on Pico-W. It is typically used to
%% drive the on-board LED.
%% @end
%%-----------------------------------------------------------------------------
-spec cyw43_arch_gpio_put(GPIO :: 0..2, Level :: 0..1) -> ok.
cyw43_arch_gpio_put(_GPIO, _Level) ->
erlang:nif_error(undefined).
4 changes: 2 additions & 2 deletions src/platforms/rp2040/pico_sdk_import.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ if (NOT PICO_SDK_PATH)
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/pguyot/pico-sdk # revert to raspberrypi once PR 1101 is merged
GIT_TAG w46/condition-variables # revert to master once PR 1101 is merged
GIT_TAG v1.5.1+conditional-variables # revert to master once PR 1101 is merged
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/pguyot/pico-sdk # revert to raspberrypi once PR 1101 is merged
GIT_TAG w46/condition-variables # revert to master once PR 1101 is merged
GIT_TAG v1.5.1+conditional-variables # revert to master once PR 1101 is merged
)
endif ()

Expand Down
4 changes: 4 additions & 0 deletions src/platforms/rp2040/src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,8 @@ if (NOT AVM_USE_32BIT_FLOAT)
target_link_libraries(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC pico_double)
endif()

if (PICO_CYW43_SUPPORTED)
target_link_libraries(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC pico_cyw43_arch_lwip_threadsafe_background)
endif()

target_link_options(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC -Wl,-u -Wl,gpio_nif)
102 changes: 102 additions & 0 deletions src/platforms/rp2040/src/lib/lwipopts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* This file is part of AtomVM.
*
* Copyright 2023 Paul Guyot <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
*/

#ifndef _LWIPOPTS_H
#define _LWIPOPTS_H

// See https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html

#define NO_SYS 1
#define LWIP_SOCKET 0
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 4000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0

#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif

#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF

#endif /* __LWIPOPTS_H__ */
Loading

0 comments on commit 0e0f38f

Please sign in to comment.