Skip to content

Commit

Permalink
Add Raspberry Pi Pico platform (#817)
Browse files Browse the repository at this point in the history
  • Loading branch information
sashacmc authored Dec 9, 2024
1 parent e492167 commit 06fb1ef
Show file tree
Hide file tree
Showing 32 changed files with 3,305 additions and 2 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/rpi_pico.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#
# Copyright (c) 2024 ZettaScale Technology
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# ZettaScale Zenoh Team, <[email protected]>
#
name: rpi_pico

on:
push:
branches: [ '**' ]
pull_request:
branches: [ '**' ]

jobs:
build:
name: Build on ${{ matrix.os }} for ${{ matrix.pico_board }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
pico_board: ["pico", "pico_w", "pico2", "pico2_w"]
steps:
- uses: actions/checkout@v4
- uses: jwlawson/[email protected]
- name: Install requirements
run: |
sudo apt update
sudo apt install -y cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential g++ libstdc++-arm-none-eabi-newlib
- name: Install Raspberry Pico SDK
run: |
export PICO_SDK_PATH=$HOME/work/pico-sdk
mkdir -p $PICO_SDK_PATH
cd $PICO_SDK_PATH
git clone https://github.com/raspberrypi/pico-sdk.git --branch 2.1.0 .
git submodule update --init
- name: Install FreeRTOS SDK
run: |
export FREERTOS_KERNEL_PATH=$HOME/work/FreeRTOS-Kernel/
mkdir -p $FREERTOS_KERNEL_PATH
cd $FREERTOS_KERNEL_PATH
git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git .
git submodule update --init
- name: Build examples
run: |
export PICO_SDK_PATH=$HOME/work/pico-sdk
export FREERTOS_KERNEL_PATH=$HOME/work/FreeRTOS-Kernel/
cd $HOME/work/zenoh-pico/zenoh-pico/examples/rpi_pico
cmake -Bbuild -DWIFI_SSID=wifi_network_ssid -DWIFI_PASSWORD=wifi_network_password -DPICO_BOARD="$PICO_BOARD"
cmake --build ./build
env:
PICO_BOARD: ${{ matrix.pico_board}}
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ include(GNUInstallDirs)
option(BUILD_SHARED_LIBS "Build shared libraries if ON, otherwise build static libraries" ON)
option(WITH_ZEPHYR "Build for Zephyr RTOS" OFF)
option(WITH_FREERTOS_PLUS_TCP "Build for FreeRTOS RTOS and FreeRTOS-Plus-TCP network stack" OFF)
option(WITH_RPI_PICO "Build for Raspberry Pi Pico" OFF)
set(ZENOH_DEBUG 0 CACHE STRING "Use this to set the ZENOH_DEBUG variable")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
if(CMAKE_EXPORT_COMPILE_COMMANDS)
Expand Down Expand Up @@ -90,7 +91,9 @@ if(CMAKE_BUILD_TYPE MATCHES "RELEASE" OR "Release")
add_compile_options(-pipe -O3)
endif()
else()
if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES "PICO")
add_compile_options(-c -Wall -Wextra -Wno-unused -Wno-strict-prototypes -pipe -g -O0)
elseif(UNIX)
add_compile_options(-c -Wall -Wextra -Werror -Wshadow -Wunused -Wstrict-prototypes -pipe -g -O0)
# C99 pedantic doesn't like struct anonymous in unix header
if (NOT CMAKE_C_STANDARD STREQUAL "99")
Expand Down Expand Up @@ -182,6 +185,9 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Generic")
elseif(WITH_FREERTOS_PLUS_TCP)
pico_add_compile_definition(ZENOH_FREERTOS_PLUS_TCP)
endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "PICO") # Raspberry Pi Pico Series
pico_add_compile_definition(ZENOH_RPI_PICO)
set(CHECK_THREADS "OFF")
else()
message(FATAL_ERROR "zenoh-pico is not yet available on ${CMAKE_SYSTEM_NAME} platform")
return()
Expand Down Expand Up @@ -226,6 +232,7 @@ set(Z_FEATURE_LINK_TCP 1 CACHE STRING "Toggle TCP links")
set(Z_FEATURE_LINK_BLUETOOTH 0 CACHE STRING "Toggle Bluetooth links")
set(Z_FEATURE_LINK_WS 0 CACHE STRING "Toggle WebSocket links")
set(Z_FEATURE_LINK_SERIAL 0 CACHE STRING "Toggle Serial links")
set(Z_FEATURE_LINK_SERIAL_USB 0 CACHE STRING "Toggle Serial USB links")
set(Z_FEATURE_SCOUTING_UDP 1 CACHE STRING "Toggle UDP scouting")
set(Z_FEATURE_LINK_UDP_MULTICAST 1 CACHE STRING "Toggle UDP multicast links")
set(Z_FEATURE_LINK_UDP_UNICAST 1 CACHE STRING "Toggle UDP unicast links")
Expand All @@ -244,6 +251,12 @@ if(Z_FEATURE_LIVELINESS AND NOT Z_FEATURE_UNSTABLE_API)
set(Z_FEATURE_LIVELINESS 0 CACHE STRING "Toggle liveliness feature" FORCE)
endif()

# Add a warning message if someone tries to enable Z_FEATURE_LINK_SERIAL_USB directly
if(Z_FEATURE_LINK_SERIAL_USB AND NOT Z_FEATURE_UNSTABLE_API)
message(WARNING "Z_FEATURE_LINK_SERIAL_USB can only be enabled when Z_FEATURE_UNSTABLE_API is also enabled. Disabling Z_FEATURE_LINK_SERIAL_USB.")
set(Z_FEATURE_LINK_SERIAL_USB 0 CACHE STRING "Toggle Serial USB links" FORCE)
endif()

add_compile_definitions("Z_BUILD_DEBUG=$<CONFIG:Debug>")
message(STATUS "Building with feature confing:\n\
* UNSTABLE_API: ${Z_FEATURE_UNSTABLE_API}\n\
Expand Down Expand Up @@ -277,6 +290,7 @@ message(STATUS "Unicast batch max size: ${BATCH_UNICAST_SIZE}")
message(STATUS "Multicast batch max size: ${BATCH_MULTICAST_SIZE}")
message(STATUS "Build for Zephyr RTOS: ${WITH_ZEPHYR}")
message(STATUS "Build for FreeRTOS-Plus-TCP: ${WITH_FREERTOS_PLUS_TCP}")
message(STATUS "Build for Raspberry Pi Pico: ${WITH_RPI_PICO}")
message(STATUS "Configuring for ${CMAKE_SYSTEM_NAME}")

if(SKBUILD)
Expand Down Expand Up @@ -338,6 +352,9 @@ if(WITH_ZEPHYR)
elseif(WITH_FREERTOS_PLUS_TCP)
file (GLOB Sources_Freertos_Plus_TCP "src/system/freertos_plus_tcp/*.c")
list(APPEND Sources ${Sources_Freertos_Plus_TCP})
elseif(WITH_RPI_PICO)
file (GLOB Sources_RPI_Pico "src/system/rpi_pico/*.c")
list(APPEND Sources ${Sources_RPI_Pico})
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin" OR CMAKE_SYSTEM_NAME MATCHES "BSD" OR POSIX_COMPATIBLE)
file (GLOB Sources_Unix "src/system/unix/*.c" "src/system/unix/link/*.c")
list(APPEND Sources ${Sources_Unix})
Expand Down
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Currently, zenoh-pico provides support for the following (RT)OSs and protocols:
| **OpenCR** | UDP (unicast and multicast), TCP | IPv4 | WiFi |
| **Emscripten** | Websocket | IPv4, IPv6 | WiFi, Ethernet |
| **FreeRTOS-Plus-TCP** | UDP (unicast), TCP | IPv4 | Ethernet |
| **Raspberry Pi Pico** | UDP (unicast and multicast), TCP | IPv4 | WiFi (for "W" version), Serial, USB (CDC) |

Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.com/eclipse-zenoh/roadmap) for more detailed information.

Expand Down Expand Up @@ -329,6 +330,92 @@ To build and upload the code into the board, run the following command:
platformio run -t upload
```

#### 2.2.6. Raspberry Pi Pico
Note: tested with `Raspberry Pi Pico W` and `Raspberry Pi Pico 2 W` boards

Ensure your system has the necessary tools and libraries installed. Run the following commands:

```bash
sudo apt update
sudo apt install -y cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential g++ libstdc++-arm-none-eabi-newlib
```

Set up the Raspberry Pi Pico SDK by cloning the repository:

```bash
export PICO_SDK_PATH=$HOME/src/pico-sdk
mkdir -p $PICO_SDK_PATH
cd $PICO_SDK_PATH
git clone https://github.com/raspberrypi/pico-sdk.git .
git submodule update --init
```

Clone the FreeRTOS Kernel repository for the project:

```bash
export FREERTOS_KERNEL_PATH=$HOME/src/FreeRTOS-Kernel/
mkdir -p $FREERTOS_KERNEL_PATH
cd $FREERTOS_KERNEL_PATH
git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git .
git submodule update --init
```

Setup and build the examples:
- `PICO_BOARD` - Pico board type: pico, pico_w, pico2, pico2_w (default: pico_w)
- `WIFI_SSID` - Wi-Fi network SSID
- `WIFI_PASSWORD` - Wi-Fi password
- `ZENOH_CONFIG_MODE` - client or peer mode (default: client)
- `ZENOH_CONFIG_CONNECT` - connect endpoint (only for client mode, optional)
- `ZENOH_CONFIG_LISTEN` - listen endpoint (only for peer mode, optional)

```bash
cd examples/rpi_pico
cmake -Bbuild -DPICO_BOARD="pico" -DWIFI_SSID=wifi_network_ssid -DWIFI_PASSWORD=wifi_network_password -DZENOH_CONFIG_MODE=[client|peer] -DZENOH_CONFIG_CONNECT=connect -DZENOH_CONFIG_LISTEN=listen
cmake --build ./build
```

To flash the Raspberry Pi Pico board, connect it in bootloader mode (it will appear as a removable drive) and copy the generated .uf2 file onto it.

**Serial connection**:

To connect via UART specify pins or predefined device name and baud rate:

e.g.
```
-DZENOH_CONFIG_CONNECT="serial/0.1#baudrate=38400"
-DZENOH_CONFIG_CONNECT="serial/uart1_0#baudrate=38400"
```

Valid PIN combinations and associated device names:

| **PINS** | **Device name** |
|---------:|:---------------:|
| 0.1 | uart0_0 |
| 4.5 | uart1_0 |
| 8.9 | uart1_1 |
| 12.13 | uart0_1 |
| 16.17 | uart0_2 |


**USB Serial connection (experemental)**:


To enable this feature, zenoh-pico should be compiled with `Z_FEATURE_LINK_SERIAL_USB` and `Z_FEATURE_UNSTABLE_API` enabled.

To connect via USB CDC, specify `usb` device:

e.g.
```
-DZENOH_CONFIG_CONNECT="serial/usb#baudrate=112500"
```

On the host Zenoh, specify the USB CDC device:

e.g.
```
zenohd -l serial//dev/ttyACM1#baudrate=112500
```

## 3. Running the Examples
The simplest way to run some of the example is to get a Docker image of the **zenoh** router (see [http://zenoh.io/docs/getting-started/quick-test/](http://zenoh.io/docs/getting-started/quick-test/)) and then to run the examples on your machine.

Expand Down
163 changes: 163 additions & 0 deletions examples/rpi_pico/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
cmake_minimum_required(VERSION 3.13)

set(PICO_BOARD "pico_w" CACHE STRING "Raspberry Pi Pico board: pico, pico_w, pico2, pico2_w")

set(WIFI_SUPPORT_ENABLED 0)
if(PICO_BOARD STREQUAL "pico_w" OR PICO_BOARD STREQUAL "pico2_w")
set(WIFI_SUPPORT_ENABLED 1)
endif()

# Set options
set(WIFI_SSID "" CACHE STRING "WiFi SSID")
set(WIFI_PASSWORD "" CACHE STRING "WiFi Password")

set(ZENOH_CONFIG_MODE "client" CACHE STRING "ZENOH_CONFIG_MODE")
set(ZENOH_CONFIG_CONNECT CACHE STRING "ZENOH_CONFIG_CONNECT")
set(ZENOH_CONFIG_LISTEN CACHE STRING "ZENOH_CONFIG_LISTEN")
option(ZENOH_USB_UART "Enable USB UART" OFF)

message(STATUS "PICO_BOARD: ${PICO_BOARD}")
message(STATUS "WIFI_SSID: ${WIFI_SSID}")
if(WIFI_PASSWORD STREQUAL "")
message(STATUS "WIFI_PASSWORD is empty")
else()
message(STATUS "WIFI_PASSWORD is set")
endif()

message(STATUS "ZENOH_CONFIG_MODE: ${ZENOH_CONFIG_MODE}")
message(STATUS "ZENOH_CONFIG_CONNECT: ${ZENOH_CONFIG_CONNECT}")
message(STATUS "ZENOH_CONFIG_LISTEN: ${ZENOH_CONFIG_LISTEN}")
message(STATUS "ZENOH_USB_UART: ${ZENOH_USB_UART}")

configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/include/config.h.in"
"${CMAKE_CURRENT_SOURCE_DIR}/include/config.h"
)

set(CMAKE_C_STANDARD 11)

# Include Raspberry Pi Pico SDK
if(NOT DEFINED ENV{PICO_SDK_PATH})
message(FATAL_ERROR "PICO_SDK_PATH environment variable is not set. Please set it to the location of the Pico SDK.")
endif()
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

# Include FreeRTOS SDK
include(FreeRTOS_Kernel_import.cmake)

# Configure project
project(zenohpico_rpi_pico_examples C CXX ASM)

if(WIFI_SUPPORT_ENABLED)
set(WIFI_LIB pico_cyw43_arch_lwip_sys_freertos)
else()
set(WIFI_LIB "")
endif()

if(ZENOH_USB_UART)
set(USB_LIBS
tinyusb_host
tinyusb_device
tinyusb_board
)
set(USB_INCLUDE
${CMAKE_CURRENT_LIST_DIR}/include/tusb
)
else()
set(USB_LIBS "")
set(USB_INCLUDE "")
endif()

add_compile_definitions(LWIP_TIMEVAL_PRIVATE=0)
pico_sdk_init()

# Include Zenoh Pico library
include(../../cmake/helpers.cmake)
set_default_build_type(Release)

if (NOT WIFI_SUPPORT_ENABLED)
declare_cache_var(Z_FEATURE_LINK_TCP 0 STRING "TCP support")
declare_cache_var(Z_FEATURE_LINK_UDP_MULTICAST 0 STRING "UDP multicast support")
declare_cache_var(Z_FEATURE_LINK_UDP_UNICAST 0 STRING "UDP unicast support")
declare_cache_var(Z_FEATURE_SCOUTING_UDP 0 STRING "Scouting support")
endif()

declare_cache_var(Z_FEATURE_LINK_SERIAL 1 STRING "Serial support")
if(ZENOH_USB_UART)
declare_cache_var(Z_FEATURE_LINK_SERIAL_USB 1 STRING "Serial USB support")
else()
declare_cache_var(Z_FEATURE_LINK_SERIAL_USB 0 STRING "Serial USB support")
endif()

set(BUILD_SHARED_LIBS OFF)
set(WITH_RPI_PICO ON)

configure_include_project(ZENOHPICO zenohpico zenohpico::lib "../.." zenohpico "https://github.com/eclipse-zenoh/zenoh-pico" "")

target_link_libraries(zenohpico_static
hardware_uart
pico_stdlib
pico_rand
FreeRTOS-Kernel-Heap4
${WIFI_LIB}
${USB_LIBS}
)

# Configure build
target_include_directories(zenohpico_static PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/include
${USB_INCLUDE}
)

add_library(main STATIC main.c)

target_include_directories(main PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/include
)
target_link_libraries(main
pico_stdlib
pico_rand
FreeRTOS-Kernel-Heap4
${WIFI_LIB}
)

function(add_example name)
add_executable(${name} ${name}.c)
target_link_libraries(${name}
main
hardware_uart
pico_stdlib
pico_rand
FreeRTOS-Kernel-Heap4
zenohpico::lib
${WIFI_LIB}
${USB_LIBS}
)
target_include_directories(${name} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/include
${USB_INCLUDE}
)
if(ZENOH_USB_UART)
pico_enable_stdio_uart(${name} 1)
pico_enable_stdio_usb(${name} 0)
else()
pico_enable_stdio_uart(${name} 0)
pico_enable_stdio_usb(${name} 1)
endif()
pico_add_extra_outputs(${name})
endfunction()

#add_example(z_get)
add_example(z_pub)
#add_example(z_pub_st)
#add_example(z_pub_thr)
#add_example(z_pull)
#add_example(z_put)
#add_example(z_queryable)
#add_example(z_scout)
#add_example(z_sub)
#add_example(z_sub_st)
#add_example(z_sub_thr)
Loading

0 comments on commit 06fb1ef

Please sign in to comment.