Skip to content

Commit

Permalink
FreeRTOS-Plus-TCP port: system and UDP unicast
Browse files Browse the repository at this point in the history
Signed-off-by: Błażej Sowa <[email protected]>
  • Loading branch information
bjsowa committed Aug 12, 2023
1 parent b68364f commit 3d954cd
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand All @@ -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)
Expand Down Expand Up @@ -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})
Expand Down
2 changes: 2 additions & 0 deletions include/zenoh-pico/system/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
26 changes: 26 additions & 0 deletions include/zenoh-pico/system/platform/freertos_plus_tcp.h
Original file line number Diff line number Diff line change
@@ -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
106 changes: 106 additions & 0 deletions src/system/freertos_plus_tcp/network.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <stdlib.h>

#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
86 changes: 86 additions & 0 deletions src/system/freertos_plus_tcp/system.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#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; }

0 comments on commit 3d954cd

Please sign in to comment.