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

FreeRTOS-Plus-TCP port #239

Merged
merged 41 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3d954cd
FreeRTOS-Plus-TCP port: system and UDP unicast
bjsowa Aug 12, 2023
2d9ed40
Fix clock_elapsed_s method
bjsowa Aug 13, 2023
d3e8cc1
Avoid double free
bjsowa Aug 14, 2023
f949eb3
Add TCP transport
bjsowa Aug 14, 2023
8e2d99d
Fix build when only TCP is enabled
bjsowa Aug 14, 2023
ba1c4c0
Initial FreeRTOS-Plus-TCP example
bjsowa Aug 25, 2023
d502492
Initial CI workflow
bjsowa Aug 25, 2023
c8c8b3d
Fix newline character in printf
bjsowa Aug 28, 2023
b86ce98
Fix network driver checksum options
bjsowa Aug 28, 2023
46bde55
Fix printf newline
bjsowa Aug 28, 2023
6314ac9
Make vAppTask static
bjsowa Aug 28, 2023
649fed5
Resolve MAC address of gateway before running Zenoh app
bjsowa Aug 28, 2023
c7cb1ef
Set zenoh debug level
bjsowa Aug 28, 2023
9965500
Increase socket timeout
bjsowa Aug 28, 2023
98be97f
Fix segfault when failed to create endpoint
bjsowa Aug 28, 2023
28fe14f
Fix warning about overflow in int conversion when using 64-bit system
bjsowa Aug 28, 2023
1390425
Use ai_family returned by getaddrinfo
bjsowa Aug 28, 2023
933324f
Fix tcp and udp read methods
bjsowa Aug 28, 2023
8633333
Retain original contributor in z_pub example
bjsowa Aug 28, 2023
1c0d0b3
Add z_scout example
bjsowa Aug 28, 2023
663724b
Base the z_pub example on unix example
bjsowa Aug 28, 2023
fe5d30e
Add more examples
bjsowa Aug 28, 2023
1581f37
Change FreeRTOS-Plus-TCP repository
bjsowa Aug 29, 2023
66e5d1c
Fix building in Release mode
bjsowa Aug 29, 2023
7fc8da0
Multi-threading initial
bjsowa Aug 29, 2023
841924c
Mark UDP Multicast as unsupported
bjsowa Aug 29, 2023
8148874
Fix _z_task_free
bjsowa Aug 29, 2023
070b5a6
Use multi-threading in examples
bjsowa Aug 29, 2023
daa800d
Add sleep to z_sub example
bjsowa Aug 29, 2023
424421d
Allow passing task attributes to read and lease tasks
bjsowa Aug 29, 2023
62556f9
Use static tasks in z_pub example
bjsowa Aug 29, 2023
a364a6e
Remove redundant print
bjsowa Aug 29, 2023
683a4d8
Add more examples
bjsowa Aug 29, 2023
5d92775
Change char* to const char*
bjsowa Aug 30, 2023
63c089b
Update license headers
bjsowa Aug 30, 2023
2291ddd
Update README
bjsowa Aug 30, 2023
a547d02
Merge branch 'master' into freertos
bjsowa Sep 21, 2023
4e81de9
Fix config keys
bjsowa Sep 21, 2023
d6d757f
Fix fprintzid
bjsowa Sep 21, 2023
376ed99
Ignore freertos_plus_tcp port sources when using PlatformIO
bjsowa Sep 21, 2023
7f9c2cf
Merge remote-tracking branch 'zenoh/master' into freertos
bjsowa Oct 26, 2023
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
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this value set by getaddrinfo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not, getaddrinfo only sets ai_family but does not write it to ai_addr->sin_family. I changed it so it at least uses the value returned by getaddrinfo.


// 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; }
bjsowa marked this conversation as resolved.
Show resolved Hide resolved

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; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will return seconds but useconds instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it. It is worth noting that the emscripten port, which I used for reference, has the same issue.


/*------------------ 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; }