From 3d954cdb94a05d4ac1040fd19dd44385898a4e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Sat, 12 Aug 2023 15:56:35 +0200 Subject: [PATCH] FreeRTOS-Plus-TCP port: system and UDP unicast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Błażej Sowa --- CMakeLists.txt | 7 ++ include/zenoh-pico/system/platform.h | 2 + .../system/platform/freertos_plus_tcp.h | 26 +++++ src/system/freertos_plus_tcp/network.c | 106 ++++++++++++++++++ src/system/freertos_plus_tcp/system.c | 86 ++++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 include/zenoh-pico/system/platform/freertos_plus_tcp.h create mode 100644 src/system/freertos_plus_tcp/network.c create mode 100644 src/system/freertos_plus_tcp/system.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 332bf0411..08e7a7ead 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ include(CMakePackageConfigHelpers) option(BUILD_SHARED_LIBS "Build shared libraries if ON, otherwise build static libraries" ON) option(ZENOH_DEBUG "Use this to set the ZENOH_DEBUG variable." 0) option(WITH_ZEPHYR "Build for Zephyr RTOS" OFF) +option(WITH_FREERTOS_PLUS_TCP "Build for FreeRTOS RTOS and FreeRTOS-Plus-TCP network stack" OFF) if(CMAKE_SYSTEM_NAME MATCHES "Windows") set(BUILD_SHARED_LIBS "OFF") @@ -85,6 +86,8 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") if(WITH_ZEPHYR) add_definition(ZENOH_ZEPHYR) + elseif(WITH_FREERTOS_PLUS_TCP) + add_definition(ZENOH_FREERTOS_PLUS_TCP) endif() else() message(FATAL_ERROR "zenoh-pico is not yet available on ${CMAKE_SYSTEM_NAME} platform") @@ -98,6 +101,7 @@ message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode") message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}") message(STATUS "Zenoh Level Log: ${ZENOH_DEBUG}") message(STATUS "Build for Zephyr RTOS: ${WITH_ZEPHYR}") +message(STATUS "Build for FreeRTOS-Plus-TCP: ${WITH_FREERTOS_PLUS_TCP}") message(STATUS "Configuring for ${CMAKE_SYSTEM_NAME}") if(SKBUILD) @@ -170,6 +174,9 @@ file(GLOB Sources "src/*.c" if(WITH_ZEPHYR) file (GLOB Sources_Zephyr "src/system/zephyr/*.c") list(APPEND Sources ${Sources_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(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") list(APPEND Sources ${Sources_Unix}) diff --git a/include/zenoh-pico/system/platform.h b/include/zenoh-pico/system/platform.h index 07e1f009e..6a76e39a0 100644 --- a/include/zenoh-pico/system/platform.h +++ b/include/zenoh-pico/system/platform.h @@ -35,6 +35,8 @@ #include "zenoh-pico/system/platform/arduino/opencr.h" #elif defined(ZENOH_EMSCRIPTEN) #include "zenoh-pico/system/platform/emscripten.h" +#elif defined(ZENOH_FREERTOS_PLUS_TCP) +#include "zenoh-pico/system/platform/freertos_plus_tcp.h" #else #include "zenoh-pico/system/platform/void.h" #error "Unknown platform" diff --git a/include/zenoh-pico/system/platform/freertos_plus_tcp.h b/include/zenoh-pico/system/platform/freertos_plus_tcp.h new file mode 100644 index 000000000..f321ef10d --- /dev/null +++ b/include/zenoh-pico/system/platform/freertos_plus_tcp.h @@ -0,0 +1,26 @@ +#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" + +typedef TickType_t z_clock_t; +typedef TickType_t z_time_t; + +typedef struct { + union { +#if Z_LINK_UDP_MULTICAST == 1 || Z_LINK_UDP_UNICAST == 1 + Socket_t _socket; +#endif + }; +} _z_sys_net_socket_t; + +typedef struct { + union { +#if Z_LINK_TCP == 1 || Z_LINK_UDP_MULTICAST == 1 || Z_LINK_UDP_UNICAST == 1 + struct freertos_addrinfo *_iptcp; +#endif + }; +} _z_sys_net_endpoint_t; + +#endif \ No newline at end of file diff --git a/src/system/freertos_plus_tcp/network.c b/src/system/freertos_plus_tcp/network.c new file mode 100644 index 000000000..523f4844a --- /dev/null +++ b/src/system/freertos_plus_tcp/network.c @@ -0,0 +1,106 @@ +#include + +#include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/pointers.h" +#include "zenoh-pico/utils/result.h" + +// FreeRTOS includes +#include "FreeRTOS.h" +#include "FreeRTOS_IP.h" + +#if Z_LINK_UDP_UNICAST == 1 || Z_LINK_UDP_MULTICAST == 1 +/*------------------ UDP sockets ------------------*/ +int8_t _z_create_endpoint_udp(_z_sys_net_endpoint_t *ep, const char *s_address, const char *s_port) { + int8_t ret = _Z_RES_OK; + + if (FreeRTOS_getaddrinfo(s_address, NULL, NULL, &ep->_iptcp) < 0) { + ret = _Z_ERR_GENERIC; + } + + ep->_iptcp->ai_addr->sin_family = FREERTOS_AF_INET4; + + // Parse and check the validity of the port + uint32_t port = strtoul(s_port, NULL, 10); + if ((port > (uint32_t)0) && (port <= (uint32_t)65355)) { // Port numbers should range from 1 to 65355 + ep->_iptcp->ai_addr->sin_port = FreeRTOS_htons((uint16_t)port); + } else { + ret = _Z_ERR_GENERIC; + } + + return ret; +} + +void _z_free_endpoint_udp(_z_sys_net_endpoint_t *ep) { FreeRTOS_freeaddrinfo(ep->_iptcp); } +#endif + +#if Z_LINK_UDP_UNICAST == 1 +int8_t _z_open_udp_unicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t rep, uint32_t tout) { + int8_t ret = _Z_RES_OK; + + sock->_socket = FreeRTOS_socket(rep._iptcp->ai_family, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP); + if (sock->_socket != FREERTOS_INVALID_SOCKET) { + TickType_t receive_timeout = pdMS_TO_TICKS(tout); + + if (FreeRTOS_setsockopt(sock->_socket, 0, FREERTOS_SO_RCVTIMEO, &receive_timeout, 0) != 0) { + ret = _Z_ERR_GENERIC; + } + + if (ret != _Z_RES_OK) { + FreeRTOS_closesocket(sock->_socket); + } + } else { + ret = _Z_ERR_GENERIC; + } + + return ret; +} + +int8_t _z_listen_udp_unicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t rep, uint32_t tout) { + int8_t ret = _Z_RES_OK; + (void)sock; + (void)rep; + (void)tout; + + // @TODO: To be implemented + ret = _Z_ERR_GENERIC; + + return ret; +} + +void _z_close_udp_unicast(_z_sys_net_socket_t *sock) { FreeRTOS_closesocket(sock->_socket); } + +size_t _z_read_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { + struct freertos_sockaddr raddr; + uint32_t addrlen = sizeof(struct freertos_sockaddr); + + int32_t rb = FreeRTOS_recvfrom(sock._socket, ptr, len, 0, &raddr, &addrlen); + if (rb < 0) { + rb = SIZE_MAX; + } + + return 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, 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 FreeRTOS_sendto(sock._socket, ptr, len, 0, rep._iptcp->ai_addr, sizeof(struct freertos_sockaddr)); +} +#endif \ No newline at end of file diff --git a/src/system/freertos_plus_tcp/system.c b/src/system/freertos_plus_tcp/system.c new file mode 100644 index 000000000..8cb6b7ee4 --- /dev/null +++ b/src/system/freertos_plus_tcp/system.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "FreeRTOS_IP.h" +#include "zenoh-pico/config.h" +#include "zenoh-pico/system/platform.h" + +/*------------------ Random ------------------*/ +uint8_t z_random_u8(void) { return z_random_u32(); } + +uint16_t z_random_u16(void) { return z_random_u32(); } + +uint32_t z_random_u32(void) { + uint32_t ret = 0; + xApplicationGetRandomNumber(&ret); + return ret; +} + +uint64_t z_random_u64(void) { + uint64_t ret = 0; + ret |= z_random_u32(); + ret = ret << 32; + ret |= z_random_u32(); + return ret; +} + +void z_random_fill(void *buf, size_t len) { + for (size_t i = 0; i < len; i++) { + *((uint8_t *)buf) = z_random_u8(); + } +} + +/*------------------ Memory ------------------*/ +void *z_malloc(size_t size) { return pvPortMalloc(size); } + +void *z_realloc(void *ptr, size_t size) { + // realloc not implemented in FreeRTOS + return NULL; +} + +void z_free(void *ptr) { vPortFree(ptr); } + +/*------------------ Sleep ------------------*/ +int z_sleep_us(size_t time) { + vTaskDelay(pdMS_TO_TICKS(time / 1000)); + return 0; +} + +int z_sleep_ms(size_t time) { + vTaskDelay(pdMS_TO_TICKS(time)); + return 0; +} + +int z_sleep_s(size_t time) { + vTaskDelay(pdMS_TO_TICKS(time * 1000)); + return 0; +} + +/*------------------ Clock ------------------*/ +z_clock_t z_clock_now(void) { return z_time_now(); } + +unsigned long z_clock_elapsed_us(z_clock_t *instant) { return z_clock_elapsed_ms(instant) * 1000; } + +unsigned long z_clock_elapsed_ms(z_clock_t *instant) { return z_time_elapsed_ms(instant); } + +unsigned long z_clock_elapsed_s(z_clock_t *instant) { return z_time_elapsed_ms(instant) * 1000; } + +/*------------------ Time ------------------*/ +z_time_t z_time_now(void) { return xTaskGetTickCount(); } + +const char *z_time_now_as_str(char *const buf, unsigned long buflen) { + snprintf(buf, buflen, "%u", z_time_now()); + return buf; +} + +unsigned long z_time_elapsed_us(z_time_t *time) { return z_time_elapsed_ms(time) * 1000; } + +unsigned long z_time_elapsed_ms(z_time_t *time) { + z_time_t now = z_time_now(); + + unsigned long elapsed = (now - *time) * portTICK_PERIOD_MS; + return elapsed; +} + +unsigned long z_time_elapsed_s(z_time_t *time) { return z_time_elapsed_ms(time) / 1000; }