This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 5e91459b1a16f0ab4dd14fc66ee4c35ec3b9af12 Author: Arjav Patel <[email protected]> AuthorDate: Sun May 31 10:11:25 2026 +0530 system/microros: Add UDP and serial custom transport backends. Micro XRCE-DDS expects the application to supply open/close/write/read callbacks for the wire transport. Add a single dispatcher that registers the selected backend via rmw_uros_set_custom_transport(), plus two backends: transport/microros_transport_udp.c BSD-socket UDP backend. Opens an AF_INET/SOCK_DGRAM socket, resolves CONFIG_MICROROS_AGENT_IP/PORT, connect()s it, and uses send/recv. The socket fd is stashed in uxrCustomTransport->args so no module-level state is needed. transport/microros_transport_serial.c termios serial backend. Opens CONFIG_MICROROS_SERIAL_DEVICE with O_RDWR|O_NOCTTY|O_CLOEXEC, switches to raw 8N1 at CONFIG_MICROROS_SERIAL_BAUD, and uses poll/read/write. Fd is again stashed in uxrCustomTransport->args. Both backends are mutually exclusive at compile time via Kconfig; the dispatcher selects which set of callbacks to register. Wired into both the legacy Make build (CSRCS in system/microros/Makefile) and the CMake build (separate microros_transport static library with the transport directory only exposed to its INTERFACE). Signed-off-by: Arjav Patel <[email protected]> --- include/system/microros_transport.h | 50 +++++ system/microros/CMakeLists.txt | 20 ++ system/microros/Makefile | 14 +- system/microros/transport/microros_transport.c | 62 ++++++ system/microros/transport/microros_transport.h | 67 +++++++ .../microros/transport/microros_transport_serial.c | 216 +++++++++++++++++++++ system/microros/transport/microros_transport_udp.c | 162 ++++++++++++++++ 7 files changed, 590 insertions(+), 1 deletion(-) diff --git a/include/system/microros_transport.h b/include/system/microros_transport.h new file mode 100644 index 000000000..fc89bde3c --- /dev/null +++ b/include/system/microros_transport.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * apps/include/system/microros_transport.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __APPS_INCLUDE_SYSTEM_MICROROS_TRANSPORT_H +#define __APPS_INCLUDE_SYSTEM_MICROROS_TRANSPORT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* microros_transport_init + * + * Register the NuttX-native transport (UDP or Serial, selected by Kconfig) + * with the rmw_microxrcedds layer. Must be called once before + * rclc_support_init(). + * + * Returns 0 on success, negated errno on failure. + */ + +int microros_transport_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_INCLUDE_SYSTEM_MICROROS_TRANSPORT_H */ diff --git a/system/microros/CMakeLists.txt b/system/microros/CMakeLists.txt index 44cd0d25b..1c3d89576 100644 --- a/system/microros/CMakeLists.txt +++ b/system/microros/CMakeLists.txt @@ -44,4 +44,24 @@ if(CONFIG_SYSTEM_MICROROS) microros PROPERTIES IMPORTED_LOCATION ${MICROROS_DIR}/libmicroros.a INTERFACE_INCLUDE_DIRECTORIES ${MICROROS_DIR}/include) add_dependencies(microros microros_build) + + # Transport glue compiled into the apps tree + set(MICROROS_TRANSPORT_SRCS ${MICROROS_DIR}/transport/microros_transport.c) + + if(CONFIG_MICROROS_TRANSPORT_UDP) + list(APPEND MICROROS_TRANSPORT_SRCS + ${MICROROS_DIR}/transport/microros_transport_udp.c) + endif() + + if(CONFIG_MICROROS_TRANSPORT_SERIAL) + list(APPEND MICROROS_TRANSPORT_SRCS + ${MICROROS_DIR}/transport/microros_transport_serial.c) + endif() + + nuttx_add_library(microros_transport STATIC) + target_sources(microros_transport PRIVATE ${MICROROS_TRANSPORT_SRCS}) + target_include_directories(microros_transport + PRIVATE ${MICROROS_DIR}/transport) + target_include_directories(microros_transport PUBLIC ${MICROROS_DIR}/include) + add_dependencies(microros_transport microros_build) endif() diff --git a/system/microros/Makefile b/system/microros/Makefile index 6d34e3cc3..18067408f 100644 --- a/system/microros/Makefile +++ b/system/microros/Makefile @@ -25,7 +25,7 @@ include $(APPDIR)/Make.defs MICROROS_DIR := $(APPDIR)/system/microros MICROROS_LIB_DIR := $(MICROROS_DIR)/micro_ros_lib MICROROS_DISTRO := $(patsubst "%",%,$(CONFIG_MICROROS_DISTRO)) -MICROROS_AR := $(CROSSDEV)ar +MICROROS_AR := $(firstword $(AR)) MAX_NODES := $(CONFIG_MICROROS_MAX_NODES) MAX_PUB := $(CONFIG_MICROROS_MAX_PUBLISHERS) @@ -44,6 +44,18 @@ ESCAPED_CXXFLAGS := $(subst /,\/,$(subst ",,$(CXXFLAGS))) MENUDESC = "micro-ROS Library" +# Transport sources compiled into the user-side app library + +CSRCS += transport/microros_transport.c + +ifeq ($(CONFIG_MICROROS_TRANSPORT_UDP),y) +CSRCS += transport/microros_transport_udp.c +endif + +ifeq ($(CONFIG_MICROROS_TRANSPORT_SERIAL),y) +CSRCS += transport/microros_transport_serial.c +endif + # Architecture for CMake toolchain ifeq ($(CONFIG_ARCH_ARM),y) MICROROS_ARCH := arm diff --git a/system/microros/transport/microros_transport.c b/system/microros/transport/microros_transport.c new file mode 100644 index 000000000..e9fdc44fa --- /dev/null +++ b/system/microros/transport/microros_transport.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * apps/system/microros/transport/microros_transport.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> + +#include <rmw_microros/rmw_microros.h> + +#include <system/microros_transport.h> + +#include "microros_transport.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int microros_transport_init(void) +{ +#if defined(CONFIG_MICROROS_TRANSPORT_UDP) + rmw_uros_set_custom_transport(false, + NULL, + microros_udp_open, + microros_udp_close, + microros_udp_write, + microros_udp_read); + return 0; +#elif defined(CONFIG_MICROROS_TRANSPORT_SERIAL) + rmw_uros_set_custom_transport(true, + NULL, + microros_serial_open, + microros_serial_close, + microros_serial_write, + microros_serial_read); + return 0; +#else + return -ENOSYS; +#endif +} diff --git a/system/microros/transport/microros_transport.h b/system/microros/transport/microros_transport.h new file mode 100644 index 000000000..4483b8ffc --- /dev/null +++ b/system/microros/transport/microros_transport.h @@ -0,0 +1,67 @@ +/**************************************************************************** + * apps/system/microros/transport/microros_transport.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __APPS_SYSTEM_MICROROS_TRANSPORT_MICROROS_TRANSPORT_H +#define __APPS_SYSTEM_MICROROS_TRANSPORT_MICROROS_TRANSPORT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <uxr/client/profile/transport/custom/custom_transport.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Backend callbacks. Exposed for testing only. */ + +bool microros_udp_open(struct uxrCustomTransport *transport); +bool microros_udp_close(struct uxrCustomTransport *transport); +size_t microros_udp_write(struct uxrCustomTransport *transport, + const uint8_t *buf, size_t len, uint8_t *err); +size_t microros_udp_read(struct uxrCustomTransport *transport, + uint8_t *buf, size_t len, + int timeout_ms, uint8_t *err); + +bool microros_serial_open(struct uxrCustomTransport *transport); +bool microros_serial_close(struct uxrCustomTransport *transport); +size_t microros_serial_write(struct uxrCustomTransport *transport, + const uint8_t *buf, size_t len, uint8_t *err); +size_t microros_serial_read(struct uxrCustomTransport *transport, + uint8_t *buf, size_t len, + int timeout_ms, uint8_t *err); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPS_SYSTEM_MICROROS_TRANSPORT_MICROROS_TRANSPORT_H */ diff --git a/system/microros/transport/microros_transport_serial.c b/system/microros/transport/microros_transport_serial.c new file mode 100644 index 000000000..6a9c7badc --- /dev/null +++ b/system/microros/transport/microros_transport_serial.c @@ -0,0 +1,216 @@ +/**************************************************************************** + * apps/system/microros/transport/microros_transport_serial.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <fcntl.h> +#include <poll.h> +#include <stdint.h> +#include <termios.h> +#include <unistd.h> + +#include "microros_transport.h" + +/**************************************************************************** + * Private Helpers + ****************************************************************************/ + +static inline int serial_fd(struct uxrCustomTransport *transport) +{ + return (int)(intptr_t)transport->args - 1; +} + +static inline void serial_set_fd(struct uxrCustomTransport *transport, + int fd) +{ + transport->args = (void *)(intptr_t)(fd + 1); +} + +static int set_baud(struct termios *tio, int baud) +{ + speed_t s; + + switch (baud) + { + case 9600: + s = B9600; + break; + + case 19200: + s = B19200; + break; + + case 38400: + s = B38400; + break; + + case 57600: + s = B57600; + break; + + case 115200: + s = B115200; + break; + + case 230400: + s = B230400; + break; + + case 460800: + s = B460800; + break; + + case 921600: + s = B921600; + break; + + default: + return -1; + } + + cfsetispeed(tio, s); + cfsetospeed(tio, s); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +bool microros_serial_open(struct uxrCustomTransport *transport) +{ + struct termios tio; + int fd; + + fd = open(CONFIG_MICROROS_SERIAL_DEVICE, O_RDWR | O_NOCTTY | O_CLOEXEC); + if (fd < 0) + { + return false; + } + + if (tcgetattr(fd, &tio) < 0) + { + close(fd); + return false; + } + + cfmakeraw(&tio); + tio.c_cflag |= (CLOCAL | CREAD); + tio.c_cflag &= ~CRTSCTS; + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 0; + + if (set_baud(&tio, CONFIG_MICROROS_SERIAL_BAUD) < 0) + { + close(fd); + return false; + } + + if (tcsetattr(fd, TCSANOW, &tio) < 0) + { + close(fd); + return false; + } + + tcflush(fd, TCIOFLUSH); + serial_set_fd(transport, fd); + return true; +} + +bool microros_serial_close(struct uxrCustomTransport *transport) +{ + int fd = serial_fd(transport); + + if (fd >= 0) + { + close(fd); + serial_set_fd(transport, -1); + } + + return true; +} + +size_t microros_serial_write(struct uxrCustomTransport *transport, + const uint8_t *buf, size_t len, uint8_t *err) +{ + int fd = serial_fd(transport); + ssize_t n; + + if (fd < 0) + { + *err = 1; + return 0; + } + + n = write(fd, buf, len); + if (n < 0) + { + *err = 1; + return 0; + } + + return n; +} + +size_t microros_serial_read(struct uxrCustomTransport *transport, + uint8_t *buf, size_t len, + int timeout_ms, uint8_t *err) +{ + int fd = serial_fd(transport); + struct pollfd pfd; + ssize_t n; + int r; + + if (fd < 0) + { + *err = 1; + return 0; + } + + pfd.fd = fd; + pfd.events = POLLIN; + + r = poll(&pfd, 1, timeout_ms); + if (r < 0) + { + *err = 1; + return 0; + } + + if (r == 0) + { + return 0; + } + + n = read(fd, buf, len); + if (n < 0) + { + *err = 1; + return 0; + } + + return n; +} diff --git a/system/microros/transport/microros_transport_udp.c b/system/microros/transport/microros_transport_udp.c new file mode 100644 index 000000000..6b048a480 --- /dev/null +++ b/system/microros/transport/microros_transport_udp.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * apps/system/microros/transport/microros_transport_udp.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <arpa/inet.h> +#include <netinet/in.h> +#include <poll.h> +#include <stdint.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include "microros_transport.h" + +/**************************************************************************** + * Private Helpers + ****************************************************************************/ + +static inline int udp_fd(struct uxrCustomTransport *transport) +{ + return (int)(intptr_t)transport->args - 1; +} + +static inline void udp_set_fd(struct uxrCustomTransport *transport, int fd) +{ + transport->args = (void *)(intptr_t)(fd + 1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +bool microros_udp_open(struct uxrCustomTransport *transport) +{ + struct sockaddr_in addr; + int fd; + + fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) + { + return false; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(CONFIG_MICROROS_AGENT_PORT); + + if (inet_pton(AF_INET, CONFIG_MICROROS_AGENT_IP, &addr.sin_addr) != 1) + { + close(fd); + return false; + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + close(fd); + return false; + } + + udp_set_fd(transport, fd); + return true; +} + +bool microros_udp_close(struct uxrCustomTransport *transport) +{ + int fd = udp_fd(transport); + + if (fd >= 0) + { + close(fd); + udp_set_fd(transport, -1); + } + + return true; +} + +size_t microros_udp_write(struct uxrCustomTransport *transport, + const uint8_t *buf, size_t len, uint8_t *err) +{ + int fd = udp_fd(transport); + ssize_t n; + + if (fd < 0) + { + *err = 1; + return 0; + } + + n = send(fd, buf, len, 0); + if (n < 0) + { + *err = 1; + return 0; + } + + return n; +} + +size_t microros_udp_read(struct uxrCustomTransport *transport, + uint8_t *buf, size_t len, + int timeout_ms, uint8_t *err) +{ + int fd = udp_fd(transport); + struct pollfd pfd; + ssize_t n; + int r; + + if (fd < 0) + { + *err = 1; + return 0; + } + + pfd.fd = fd; + pfd.events = POLLIN; + + r = poll(&pfd, 1, timeout_ms); + if (r < 0) + { + *err = 1; + return 0; + } + + if (r == 0) + { + return 0; + } + + n = recv(fd, buf, len, 0); + if (n < 0) + { + *err = 1; + return 0; + } + + return n; +}
