From b04f08fac0c2947b68d613985f88ee2b63e88912 Mon Sep 17 00:00:00 2001 From: Alexander Bushnev Date: Wed, 4 Dec 2024 17:03:31 +0100 Subject: [PATCH] Add serial port support --- README.md | 2 +- examples/rpi_pico_w/CMakeLists.txt | 16 +- examples/rpi_pico_w/include/config.h | 10 + examples/rpi_pico_w/include/config.h.in | 10 + examples/rpi_pico_w/main.c | 23 +- examples/rpi_pico_w/z_get.c | 7 +- examples/rpi_pico_w/z_pub.c | 7 +- examples/rpi_pico_w/z_pub_st.c | 7 +- examples/rpi_pico_w/z_pub_thr.c | 7 +- examples/rpi_pico_w/z_pull.c | 7 +- examples/rpi_pico_w/z_put.c | 7 +- examples/rpi_pico_w/z_queryable.c | 7 +- examples/rpi_pico_w/z_scout.c | 2 + examples/rpi_pico_w/z_sub.c | 7 +- examples/rpi_pico_w/z_sub_st.c | 7 +- examples/rpi_pico_w/z_sub_thr.c | 7 +- include/zenoh-pico/config.h | 2 +- .../zenoh-pico/system/platform/rpi_pico_w.h | 9 + src/system/rpi_pico_w/network.c | 220 +++++++++++++++++- 19 files changed, 311 insertions(+), 53 deletions(-) create mode 100644 examples/rpi_pico_w/include/config.h create mode 100644 examples/rpi_pico_w/include/config.h.in diff --git a/README.md b/README.md index 1eac13121..2fc8dc562 100644 --- a/README.md +++ b/README.md @@ -34,7 +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 W**| UDP (unicast and multicast), TCP | IPv4 | WiFi | +|**Raspberry Pi Pico W**| UDP (unicast and multicast), TCP | IPv4 | WiFi, Serial | Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.com/eclipse-zenoh/roadmap) for more detailed information. diff --git a/examples/rpi_pico_w/CMakeLists.txt b/examples/rpi_pico_w/CMakeLists.txt index c688bf0b7..6afd95dbc 100644 --- a/examples/rpi_pico_w/CMakeLists.txt +++ b/examples/rpi_pico_w/CMakeLists.txt @@ -19,6 +19,11 @@ message(STATUS "ZENOH_CONFIG_MODE: ${ZENOH_CONFIG_MODE}") message(STATUS "ZENOH_CONFIG_CONNECT: ${ZENOH_CONFIG_CONNECT}") message(STATUS "ZENOH_CONFIG_LISTEN: ${ZENOH_CONFIG_LISTEN}") +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 @@ -46,6 +51,7 @@ set(WITH_RPI_PICO_W 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_cyw43_arch_lwip_sys_freertos FreeRTOS-Kernel-Heap4 @@ -59,10 +65,6 @@ target_include_directories(zenohpico_static PRIVATE add_library(main STATIC main.c) -target_compile_definitions(main PRIVATE - WIFI_SSID=\"${WIFI_SSID}\" - WIFI_PASSWORD=\"${WIFI_PASSWORD}\" -) target_include_directories(main PRIVATE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/include @@ -77,16 +79,12 @@ function(add_example name) add_executable(${name} ${name}.c) target_link_libraries(${name} main + hardware_uart pico_stdlib pico_cyw43_arch_lwip_sys_freertos FreeRTOS-Kernel-Heap4 zenohpico::lib ) - target_compile_definitions(${name} PRIVATE - ZENOH_CONFIG_MODE=\"${ZENOH_CONFIG_MODE}\" - ZENOH_CONFIG_CONNECT=\"${ZENOH_CONFIG_CONNECT}\" - ZENOH_CONFIG_LISTEN=\"${ZENOH_CONFIG_LISTEN}\" - ) target_include_directories(${name} PRIVATE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/include diff --git a/examples/rpi_pico_w/include/config.h b/examples/rpi_pico_w/include/config.h new file mode 100644 index 000000000..c115cf39e --- /dev/null +++ b/examples/rpi_pico_w/include/config.h @@ -0,0 +1,10 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define WIFI_SSID "" +#define WIFI_PASSWORD "" +#define ZENOH_CONFIG_MODE "client" +#define ZENOH_CONFIG_CONNECT "serial/uart1_0#baudrate=38400" +#define ZENOH_CONFIG_LISTEN "" + +#endif // CONFIG_H diff --git a/examples/rpi_pico_w/include/config.h.in b/examples/rpi_pico_w/include/config.h.in new file mode 100644 index 000000000..0ad957d41 --- /dev/null +++ b/examples/rpi_pico_w/include/config.h.in @@ -0,0 +1,10 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define WIFI_SSID "@WIFI_SSID@" +#define WIFI_PASSWORD "@WIFI_PASSWORD@" +#define ZENOH_CONFIG_MODE "@ZENOH_CONFIG_MODE@" +#define ZENOH_CONFIG_CONNECT "@ZENOH_CONFIG_CONNECT@" +#define ZENOH_CONFIG_LISTEN "@ZENOH_CONFIG_LISTEN@" + +#endif // CONFIG_H diff --git a/examples/rpi_pico_w/main.c b/examples/rpi_pico_w/main.c index 42143d0f6..4bf328b83 100644 --- a/examples/rpi_pico_w/main.c +++ b/examples/rpi_pico_w/main.c @@ -13,6 +13,7 @@ // #include "FreeRTOS.h" +#include "config.h" #include "pico/cyw43_arch.h" #include "pico/stdlib.h" #include "task.h" @@ -35,19 +36,27 @@ void print_ip_address() { void main_task(void *params) { (void)params; + + vTaskDelay(pdMS_TO_TICKS(1000)); + if (cyw43_arch_init()) { printf("Failed to initialise\n"); return; } - cyw43_arch_enable_sta_mode(); - printf("Connecting to Wi-Fi...\n"); - if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, WIFI_TIMEOUT) == 0) { - printf("Wi-Fi connected.\n"); - print_ip_address(); - app_main(); + if (strlen(WIFI_SSID) != 0) { + cyw43_arch_enable_sta_mode(); + printf("Connecting to Wi-Fi...\n"); + if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, WIFI_TIMEOUT) == 0) { + printf("Wi-Fi connected.\n"); + print_ip_address(); + app_main(); + } else { + printf("Failed to connect Wi-Fi\n"); + } } else { - printf("Failed to connect Wi-Fi\n"); + printf("Offline mode\n"); + app_main(); } printf("Terminate.\n"); diff --git a/examples/rpi_pico_w/z_get.c b/examples/rpi_pico_w/z_get.c index a0f713de8..db0d85473 100644 --- a/examples/rpi_pico_w/z_get.c +++ b/examples/rpi_pico_w/z_get.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_QUERY == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/**" #define VALUE "" @@ -52,8 +53,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_pub.c b/examples/rpi_pico_w/z_pub.c index 1d5e554e4..9ffcbcfe1 100644 --- a/examples/rpi_pico_w/z_pub.c +++ b/examples/rpi_pico_w/z_pub.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_PUBLICATION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/zenoh-pico-pub" #define VALUE "[RPI] Pub from Zenoh-Pico!" @@ -30,8 +31,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_pub_st.c b/examples/rpi_pico_w/z_pub_st.c index 963918330..83233da5e 100644 --- a/examples/rpi_pico_w/z_pub_st.c +++ b/examples/rpi_pico_w/z_pub_st.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_PUBLICATION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/zenoh-pico-pub" #define VALUE "[RPI] Pub from Zenoh-Pico!" @@ -30,8 +31,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_pub_thr.c b/examples/rpi_pico_w/z_pub_thr.c index 38f63be56..29882d432 100644 --- a/examples/rpi_pico_w/z_pub_thr.c +++ b/examples/rpi_pico_w/z_pub_thr.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_PUBLICATION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "test/thr" #define PAYLOAD_SIZE 8 @@ -39,8 +40,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_pull.c b/examples/rpi_pico_w/z_pull.c index f808f12d6..175815e0d 100644 --- a/examples/rpi_pico_w/z_pull.c +++ b/examples/rpi_pico_w/z_pull.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_SUBSCRIPTION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/**" const size_t INTERVAL = 5000; @@ -32,8 +33,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_put.c b/examples/rpi_pico_w/z_put.c index fe393bb87..bff22a1e8 100644 --- a/examples/rpi_pico_w/z_put.c +++ b/examples/rpi_pico_w/z_put.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_PUBLICATION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/zenoh-pico-pub" #define VALUE "[RPI] Pub from Zenoh-Pico!" @@ -30,8 +31,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_queryable.c b/examples/rpi_pico_w/z_queryable.c index c3b9c31fb..dc36f2403 100644 --- a/examples/rpi_pico_w/z_queryable.c +++ b/examples/rpi_pico_w/z_queryable.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_QUERYABLE == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/zenoh-pico-queryable" #define VALUE "[RPI] Queryable from Zenoh-Pico!" @@ -56,8 +57,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_scout.c b/examples/rpi_pico_w/z_scout.c index 0611d61ee..01ce5e935 100644 --- a/examples/rpi_pico_w/z_scout.c +++ b/examples/rpi_pico_w/z_scout.c @@ -18,6 +18,8 @@ #include #include +#include "config.h" + void fprintzid(FILE *stream, z_id_t zid) { unsigned int zidlen = _z_id_len(zid); if (zidlen == 0) { diff --git a/examples/rpi_pico_w/z_sub.c b/examples/rpi_pico_w/z_sub.c index 2f9aecfdf..ea891a628 100644 --- a/examples/rpi_pico_w/z_sub.c +++ b/examples/rpi_pico_w/z_sub.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_SUBSCRIPTION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/**" void data_handler(z_loaned_sample_t *sample, void *ctx) { @@ -40,8 +41,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_sub_st.c b/examples/rpi_pico_w/z_sub_st.c index 2acfd608a..aba1da9b2 100644 --- a/examples/rpi_pico_w/z_sub_st.c +++ b/examples/rpi_pico_w/z_sub_st.c @@ -15,9 +15,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_SUBSCRIPTION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "demo/example/zenoh-pico-pub" #define VALUE "[RPI] Pub from Zenoh-Pico!" int msg_nb = 0; @@ -43,8 +44,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/examples/rpi_pico_w/z_sub_thr.c b/examples/rpi_pico_w/z_sub_thr.c index 083d3f956..f3e4d09b6 100644 --- a/examples/rpi_pico_w/z_sub_thr.c +++ b/examples/rpi_pico_w/z_sub_thr.c @@ -19,9 +19,10 @@ #include #include +#include "config.h" + #if Z_FEATURE_SUBSCRIPTION == 1 -#define IFACE "#iface=lo" // Not used by this platform, but should be present #define KEYEXPR "test/thr" #define PACKET_NB 1000000 @@ -78,8 +79,8 @@ void app_main(void) { zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, ZENOH_CONFIG_CONNECT); } if (strcmp(ZENOH_CONFIG_LISTEN, "") != 0) { - printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN IFACE); - zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN IFACE); + printf("Listen endpoint: %s\n", ZENOH_CONFIG_LISTEN); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, ZENOH_CONFIG_LISTEN); } printf("Opening %s session ...\n", ZENOH_CONFIG_MODE); diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 1578b1f50..8228c2252 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -34,7 +34,7 @@ #define Z_FEATURE_LINK_TCP 1 #define Z_FEATURE_LINK_BLUETOOTH 0 #define Z_FEATURE_LINK_WS 0 -#define Z_FEATURE_LINK_SERIAL 0 +#define Z_FEATURE_LINK_SERIAL 1 #define Z_FEATURE_SCOUTING_UDP 1 #define Z_FEATURE_LINK_UDP_MULTICAST 1 #define Z_FEATURE_LINK_UDP_UNICAST 1 diff --git a/include/zenoh-pico/system/platform/rpi_pico_w.h b/include/zenoh-pico/system/platform/rpi_pico_w.h index ac01fefee..2610e2897 100644 --- a/include/zenoh-pico/system/platform/rpi_pico_w.h +++ b/include/zenoh-pico/system/platform/rpi_pico_w.h @@ -17,7 +17,13 @@ #include "FreeRTOS.h" #include "event_groups.h" +#if Z_FEATURE_LINK_TCP == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 || Z_FEATURE_LINK_UDP_UNICAST == 1 #include "lwip/ip4_addr.h" +#endif +#if Z_FEATURE_LINK_SERIAL == 1 +#include "hardware/gpio.h" +#include "hardware/uart.h" +#endif #include "semphr.h" #ifdef __cplusplus @@ -51,6 +57,9 @@ typedef struct { union { #if Z_FEATURE_LINK_TCP == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 || Z_FEATURE_LINK_UDP_UNICAST == 1 int _fd; +#endif +#if Z_FEATURE_LINK_SERIAL == 1 + uart_inst_t *_serial; #endif }; } _z_sys_net_socket_t; diff --git a/src/system/rpi_pico_w/network.c b/src/system/rpi_pico_w/network.c index aed835cd9..174b59174 100644 --- a/src/system/rpi_pico_w/network.c +++ b/src/system/rpi_pico_w/network.c @@ -22,7 +22,10 @@ #include "lwip/udp.h" #include "pico/cyw43_arch.h" #include "zenoh-pico/collections/string.h" +#include "zenoh-pico/system/link/serial.h" #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/checksum.h" +#include "zenoh-pico/utils/encoding.h" #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/result.h" @@ -476,14 +479,221 @@ size_t _z_send_udp_multicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, #endif -#if Z_FEATURE_LINK_BLUETOOTH == 1 -#error "Bluetooth not supported yet on Raspberry Pico W port of Zenoh-Pico" +#if Z_FEATURE_LINK_SERIAL == 1 + +// Define allowed TX/RX pin combinations for UART0 and UART1 +static const struct { + uint32_t tx_pin; + uint32_t rx_pin; + uart_inst_t *uart; + const char *alias; +} allowed_uart_pins[] = {{0, 1, uart0, "uart0_0"}, + {4, 5, uart1, "uart1_0"}, + {8, 9, uart1, "uart1_1"}, + {12, 13, uart0, "uart0_1"}, + {16, 17, uart0, "uart0_2"}}; + +#define NUM_UART_PIN_COMBINATIONS (sizeof(allowed_uart_pins) / sizeof(allowed_uart_pins[0])) + +static void _z_open_serial_impl(uart_inst_t *uart, uint32_t txpin, uint32_t rxpin, uint32_t baudrate) { + uart_init(uart, baudrate); + + gpio_set_function(txpin, UART_FUNCSEL_NUM(uart, txpin)); + gpio_set_function(rxpin, UART_FUNCSEL_NUM(uart, rxpin)); + + uart_set_format(uart, 8, 1, UART_PARITY_NONE); // 8-N-1: Default in Zenoh Rust +} + +z_result_t _z_open_serial_from_pins(_z_sys_net_socket_t *sock, uint32_t txpin, uint32_t rxpin, uint32_t baudrate) { + z_result_t ret = _Z_RES_OK; + + if (!sock || baudrate == 0) { + return _Z_ERR_INVALID; + } + + sock->_serial = NULL; + + for (size_t i = 0; i < NUM_UART_PIN_COMBINATIONS; i++) { + if (allowed_uart_pins[i].tx_pin == txpin && allowed_uart_pins[i].rx_pin == rxpin) { + sock->_serial = allowed_uart_pins[i].uart; + break; + } + } + + if (sock->_serial == NULL) { + return _Z_ERR_INVALID; + } + + _z_open_serial_impl(sock->_serial, txpin, rxpin, baudrate); + + return ret; +} + +z_result_t _z_open_serial_from_dev(_z_sys_net_socket_t *sock, char *dev, uint32_t baudrate) { + z_result_t ret = _Z_RES_OK; + + if (!sock || baudrate == 0) { + return _Z_ERR_INVALID; + } + + sock->_serial = NULL; + uint32_t txpin = 0; + uint32_t rxpin = 0; + + for (size_t i = 0; i < NUM_UART_PIN_COMBINATIONS; i++) { + if (strcmp(allowed_uart_pins[i].alias, dev) == 0) { + sock->_serial = allowed_uart_pins[i].uart; + txpin = allowed_uart_pins[i].tx_pin; + rxpin = allowed_uart_pins[i].rx_pin; + break; + } + } + + if (sock->_serial == NULL) { + return _Z_ERR_INVALID; + } + + _z_open_serial_impl(sock->_serial, txpin, rxpin, baudrate); + + return ret; +} + +z_result_t _z_listen_serial_from_pins(_z_sys_net_socket_t *sock, uint32_t txpin, uint32_t rxpin, uint32_t baudrate) { + z_result_t ret = _Z_RES_OK; + (void)(sock); + (void)(txpin); + (void)(rxpin); + (void)(baudrate); + + // @TODO: To be implemented + ret = _Z_ERR_GENERIC; + + return ret; +} + +z_result_t _z_listen_serial_from_dev(_z_sys_net_socket_t *sock, char *dev, uint32_t baudrate) { + z_result_t ret = _Z_RES_OK; + (void)(sock); + (void)(dev); + (void)(baudrate); + + // @TODO: To be implemented + ret = _Z_ERR_GENERIC; + + return ret; +} + +void _z_close_serial(_z_sys_net_socket_t *sock) { uart_deinit(sock->_serial); } + +size_t _z_read_serial(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { + z_result_t ret = _Z_RES_OK; + + uint8_t *before_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MAX_COBS_BUF_SIZE); + size_t rb = 0; + for (size_t i = 0; i < _Z_SERIAL_MAX_COBS_BUF_SIZE; i++) { + before_cobs[i] = uart_getc(sock._serial); + + rb = rb + (size_t)1; + if (before_cobs[i] == (uint8_t)0x00) { + break; + } + } + + uint8_t *after_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MFS_SIZE); + size_t trb = _z_cobs_decode(before_cobs, rb, after_cobs); + + size_t i = 0; + uint16_t payload_len = 0; + for (; i < sizeof(payload_len); i++) { + payload_len |= (after_cobs[i] << ((uint8_t)i * (uint8_t)8)); + } + + if (trb == (size_t)(payload_len + (uint16_t)6)) { + (void)memcpy(ptr, &after_cobs[i], payload_len); + i = i + (size_t)payload_len; + + uint32_t crc = 0; + for (uint8_t j = 0; j < sizeof(crc); j++) { + crc |= (uint32_t)(after_cobs[i] << (j * (uint8_t)8)); + i = i + (size_t)1; + } + + uint32_t c_crc = _z_crc32(ptr, payload_len); + if (c_crc != crc) { + ret = _Z_ERR_GENERIC; + } + } else { + ret = _Z_ERR_GENERIC; + } + + z_free(before_cobs); + z_free(after_cobs); + + rb = payload_len; + if (ret != _Z_RES_OK) { + rb = SIZE_MAX; + } + + return rb; +} + +size_t _z_read_exact_serial(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_serial(sock, ptr, 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_serial(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len) { + z_result_t ret = _Z_RES_OK; + + uint8_t *before_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MFS_SIZE); + size_t i = 0; + for (; i < sizeof(uint16_t); ++i) { + before_cobs[i] = (len >> (i * (size_t)8)) & (size_t)0XFF; + } + + (void)memcpy(&before_cobs[i], ptr, len); + i = i + len; + + uint32_t crc = _z_crc32(ptr, len); + for (uint8_t j = 0; j < sizeof(crc); j++) { + before_cobs[i] = (crc >> (j * (uint8_t)8)) & (uint32_t)0XFF; + i = i + (size_t)1; + } + + uint8_t *after_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MAX_COBS_BUF_SIZE); + ssize_t twb = _z_cobs_encode(before_cobs, i, after_cobs); + after_cobs[twb] = 0x00; // Manually add the COBS delimiter + uart_write_blocking(sock._serial, after_cobs, twb + (ssize_t)1); + + z_free(before_cobs); + z_free(after_cobs); + + size_t sb = len; + if (ret != _Z_RES_OK) { + sb = SIZE_MAX; + } + + return sb; +} #endif -#if Z_FEATURE_LINK_SERIAL == 1 -#error "Serial not supported yet on Raspberry Pico W port of Zenoh-Pico" +#if Z_FEATURE_LINK_BLUETOOTH == 1 +#error "Bluetooth not supported yet on Raspberry Pi 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" +#error "Raw ethernet transport not supported yet on Raspberry Pi Pico W port of Zenoh-Pico" #endif