Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Raspberry Pi Pico platform #817

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading