Skip to content

Commit

Permalink
Add base rpi_pico_w platform
Browse files Browse the repository at this point in the history
  • Loading branch information
sashacmc committed Dec 2, 2024
1 parent c21ce85 commit 8f4ddb8
Show file tree
Hide file tree
Showing 6 changed files with 600 additions and 1 deletion.
7 changes: 7 additions & 0 deletions 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_W "Build for Raspberry Pico W" 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 @@ -181,6 +182,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Generic")
pico_add_compile_definition(ZENOH_ZEPHYR)
elseif(WITH_FREERTOS_PLUS_TCP)
pico_add_compile_definition(ZENOH_FREERTOS_PLUS_TCP)
elseif(WITH_RPI_PICO_W)
pico_add_compile_definition(ZENOH_RPI_PICO_W)
endif()
else()
message(FATAL_ERROR "zenoh-pico is not yet available on ${CMAKE_SYSTEM_NAME} platform")
Expand Down Expand Up @@ -273,6 +276,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 Pico W: ${WITH_RPI_PICO_W}")
message(STATUS "Configuring for ${CMAKE_SYSTEM_NAME}")

if(SKBUILD)
Expand Down Expand Up @@ -334,6 +338,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_W)
file (GLOB Sources_RPI_Pico_W "src/system/rpi_pico_w/*.c")
list(APPEND Sources ${Sources_RPI_Pico_W})
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
2 changes: 1 addition & 1 deletion examples/rpi_pico_w/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pico_enable_stdio_usb(zenohpico_rpi_pico_w_examples 1)
pico_enable_stdio_uart(zenohpico_rpi_pico_w_examples 1)

set(BUILD_SHARED_LIBS OFF)
set(WITH_FREERTOS_PLUS_TCP ON)
set(WITH_RPI_PICO_W ON)
set(ZENOH_DEBUG 5)
#add_compile_options(-Wno-strict-prototypes)
#add_compile_options(-Wno-pragmas)
Expand Down
71 changes: 71 additions & 0 deletions include/zenoh-pico/system/platform/rpi_pico_w.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright (c) 2023 Fictionlab sp. z o.o.
//
// 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:
// Błażej Sowa, <[email protected]>

#ifndef ZENOH_PICO_SYSTEM_FREERTOS_PLUS_TCP_TYPES_H
#define ZENOH_PICO_SYSTEM_FREERTOS_PLUS_TCP_TYPES_H

#include "FreeRTOS.h"
// #include "FreeRTOS_IP.h"
#include "event_groups.h"
#include "lwip/ip4_addr.h"
#include "semphr.h"

#ifdef __cplusplus
extern "C" {
#endif

#if Z_FEATURE_MULTI_THREAD == 1
typedef struct {
const char *name;
UBaseType_t priority;
size_t stack_depth;
#if (configSUPPORT_STATIC_ALLOCATION == 1)
bool static_allocation;
StackType_t *stack_buffer;
StaticTask_t *task_buffer;
#endif /* SUPPORT_STATIC_ALLOCATION */
} z_task_attr_t;

typedef struct {
TaskHandle_t handle;
EventGroupHandle_t join_event;
} _z_task_t;

typedef SemaphoreHandle_t _z_mutex_t;
typedef void *_z_condvar_t;
#endif // Z_MULTI_THREAD == 1

typedef struct timespec z_clock_t;
typedef struct timeval z_time_t;

typedef struct {
union {
#if Z_FEATURE_LINK_TCP == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 || Z_FEATURE_LINK_UDP_UNICAST == 1
int _fd;
#endif
};
} _z_sys_net_socket_t;

typedef struct {
union {
#if Z_FEATURE_LINK_TCP == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 || Z_FEATURE_LINK_UDP_UNICAST == 1
struct addrinfo *_iptcp;
#endif
};
} _z_sys_net_endpoint_t;

#ifdef __cplusplus
}
#endif

#endif
2 changes: 2 additions & 0 deletions include/zenoh-pico/system/platform_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#include "zenoh-pico/system/platform/flipper.h"
#elif defined(ZENOH_FREERTOS_PLUS_TCP)
#include "zenoh-pico/system/platform/freertos_plus_tcp.h"
#elif defined(ZENOH_RPI_PICO_W)
#include "zenoh-pico/system/platform/rpi_pico_w.h"
#else
#include "zenoh-pico/system/platform/void.h"
#error "Unknown platform"
Expand Down
264 changes: 264 additions & 0 deletions src/system/rpi_pico_w/network.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
//
// 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]>

#include <stdlib.h>

#include "lwip/dns.h"
#include "lwip/ip4_addr.h"
#include "lwip/netdb.h"
#include "lwip/pbuf.h"
#include "lwip/sockets.h"
#include "lwip/udp.h"
#include "zenoh-pico/system/platform.h"
#include "zenoh-pico/utils/logging.h"
#include "zenoh-pico/utils/pointers.h"
#include "zenoh-pico/utils/result.h"

#if Z_FEATURE_LINK_TCP == 1
/*------------------ TCP sockets ------------------*/
z_result_t _z_create_endpoint_tcp(_z_sys_net_endpoint_t *ep, const char *s_address, const char *s_port) {
z_result_t ret = _Z_RES_OK;

struct addrinfo hints;
(void)memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = IPPROTO_TCP;

if (getaddrinfo(s_address, s_port, &hints, &ep->_iptcp) < 0) {
ret = _Z_ERR_GENERIC;
}

_Z_DEBUG("_z_create_endpoint_tcp: %s:%s -> %li", s_address, s_port, ep->_iptcp->ai_addrlen);
return ret;
}

void _z_free_endpoint_tcp(_z_sys_net_endpoint_t *ep) { freeaddrinfo(ep->_iptcp); }

z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t rep, uint32_t tout) {
z_result_t ret = _Z_RES_OK;

sock->_fd = socket(rep._iptcp->ai_family, rep._iptcp->ai_socktype, rep._iptcp->ai_protocol);
if (sock->_fd != -1) {
// TODO: check what options not supported
/*
z_time_t tv;
tv.tv_sec = tout / (uint32_t)1000;
tv.tv_usec = (tout % (uint32_t)1000) * (uint32_t)1000;
if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) < 0)) {
ret = _Z_ERR_GENERIC;
}
int flags = 1;
if ((ret == _Z_RES_OK) &&
(setsockopt(sock->_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)) < 0)) {
ret = _Z_ERR_GENERIC;
}
#if Z_FEATURE_TCP_NODELAY == 1
if ((ret == _Z_RES_OK) &&
(setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0)) {
ret = _Z_ERR_GENERIC;
}
#endif
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = Z_TRANSPORT_LEASE / 1000;
if ((ret == _Z_RES_OK) &&
(setsockopt(sock->_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(struct linger)) < 0)) {
ret = _Z_ERR_GENERIC;
}
*/
struct addrinfo *it = NULL;
for (it = rep._iptcp; it != NULL; it = it->ai_next) {
if ((ret == _Z_RES_OK) && (connect(sock->_fd, it->ai_addr, it->ai_addrlen) < 0)) {
if (it->ai_next == NULL) {
ret = _Z_ERR_GENERIC;
break;
}
} else {
break;
}
}

if (ret != _Z_RES_OK) {
close(sock->_fd);
}
} else {
ret = _Z_ERR_GENERIC;
}

return ret;
}

z_result_t _z_listen_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t lep) {
z_result_t ret = _Z_RES_OK;
(void)sock;
(void)lep;

// @TODO: To be implemented
ret = _Z_ERR_GENERIC;

return ret;
}

void _z_close_tcp(_z_sys_net_socket_t *sock) {
shutdown(sock->_fd, SHUT_RDWR);
close(sock->_fd);
}

size_t _z_read_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) {
ssize_t rb = recv(sock._fd, ptr, len, 0);
if (rb < (ssize_t)0) {
return SIZE_MAX;
}

return (size_t)rb;
}

size_t _z_read_exact_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) {
size_t n = 0;
uint8_t *pos = &ptr[0];

do {
size_t rb = _z_read_tcp(sock, pos, len - n);
if (rb == SIZE_MAX) {
n = rb;
break;
}

n = n + rb;
pos = _z_ptr_u8_offset(pos, n);
} while (n != len);

return n;
}

size_t _z_send_tcp(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len) {
#if defined(ZENOH_LINUX)
return (size_t)send(sock._fd, ptr, len, MSG_NOSIGNAL);
#else
return send(sock._fd, ptr, len, 0);
#endif
}
#endif

#if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1
/*------------------ UDP sockets ------------------*/
z_result_t _z_create_endpoint_udp(_z_sys_net_endpoint_t *ep, const char *s_address, const char *s_port) {
z_result_t ret = _Z_RES_OK;

struct addrinfo hints;
(void)memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = IPPROTO_UDP;

if (getaddrinfo(s_address, s_port, &hints, &ep->_iptcp) < 0) {
ret = _Z_ERR_GENERIC;
}

return ret;
}

void _z_free_endpoint_udp(_z_sys_net_endpoint_t *ep) { freeaddrinfo(ep->_iptcp); }
#endif

#if Z_FEATURE_LINK_UDP_UNICAST == 1
z_result_t _z_open_udp_unicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t rep, uint32_t tout) {
z_result_t ret = _Z_RES_OK;

sock->_fd = socket(rep._iptcp->ai_family, rep._iptcp->ai_socktype, rep._iptcp->ai_protocol);
if (sock->_fd != -1) {
z_time_t tv;
tv.tv_sec = tout / (uint32_t)1000;
tv.tv_usec = (tout % (uint32_t)1000) * (uint32_t)1000;
if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) < 0)) {
ret = _Z_ERR_GENERIC;
}

if (ret != _Z_RES_OK) {
close(sock->_fd);
}
} else {
ret = _Z_ERR_GENERIC;
}

return ret;
}

z_result_t _z_listen_udp_unicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t lep, uint32_t tout) {
(void)sock;
(void)lep;
(void)tout;

// @TODO: To be implemented
ret = _Z_ERR_GENERIC;

return ret;
}

void _z_close_udp_unicast(_z_sys_net_socket_t *sock) { close(sock->_fd); }

size_t _z_read_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) {
struct sockaddr_storage raddr;
unsigned int addrlen = sizeof(struct sockaddr_storage);

ssize_t rb = recvfrom(sock._fd, ptr, len, 0, (struct sockaddr *)&raddr, &addrlen);
if (rb < (ssize_t)0) {
return SIZE_MAX;
}
return (size_t)rb;
}

size_t _z_read_exact_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) {
size_t n = 0;
uint8_t *pos = &ptr[0];

do {
size_t rb = _z_read_udp_unicast(sock, pos, len - n);
if (rb == SIZE_MAX) {
n = rb;
break;
}

n = n + rb;
pos = _z_ptr_u8_offset(pos, (ptrdiff_t)n);
} while (n != len);

return n;
}

size_t _z_send_udp_unicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len,
const _z_sys_net_endpoint_t rep) {
return (size_t)sendto(sock._fd, ptr, len, 0, rep._iptcp->ai_addr, rep._iptcp->ai_addrlen);
}
#endif

#if Z_FEATURE_LINK_UDP_MULTICAST == 1
#error "UDP Multicast not supported yet on Raspberry Pico W port of Zenoh-Pico"
#endif

#if Z_FEATURE_LINK_BLUETOOTH == 1
#error "Bluetooth not supported yet on Raspberry Pico W port of Zenoh-Pico"
#endif

#if Z_FEATURE_LINK_SERIAL == 1
#error "Serial not supported yet on Raspberry Pico W port of Zenoh-Pico"
#endif

#if Z_FEATURE_RAWETH_TRANSPORT == 1
#error "Raw ethernet transport not supported yet on Raspberry Pico W port of Zenoh-Pico"
#endif
Loading

0 comments on commit 8f4ddb8

Please sign in to comment.