diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml old mode 100755 new mode 100644 index 34ab831..b6fb812 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,71 +1,53 @@ name: CI on: + workflow_dispatch: + inputs: + name: + description: "Manual trigger" pull_request: - branches: - - '**' + branches: ["rolling", "jazzy", "humble"] jobs: micro_ros_zephyr_module: runs-on: ubuntu-latest - container: ubuntu:22.04 + container: + image: zephyrprojectrtos/ci:v0.26.17 + options: --user root + env: + CMAKE_PREFIX_PATH: /opt/toolchains strategy: fail-fast: false matrix: - zephyr_version: ["zephyr-v3.1.0", "zephyr-v2.7.2"] - include: - - zephyr_version: zephyr-v2.7.2 - zephyr_sdk: 0.14.2 - sdk_filename: zephyr-sdk-$TOOLCHAIN_VERSION\_linux-x86_64_minimal.tar.gz - - zephyr_version: zephyr-v3.1.0 - zephyr_sdk: 0.14.2 - sdk_filename: zephyr-sdk-$TOOLCHAIN_VERSION\_linux-x86_64_minimal.tar.gz + zephyr_version: ["v4.0.0", "v4.1.0"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: path: micro_ros_zephyr_module - name: Build shell: bash run: | - # Install dependencies - apt update - export DEBIAN_FRONTEND=noninteractive - apt install -y --no-install-recommends wget git cmake ninja-build gperf \ - ccache dfu-util device-tree-compiler wget \ - python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \ - make gcc gcc-multilib g++-multilib libsdl2-dev - - # Install Zephyr environment - pip3 install --user -U west - export PATH=~/.local/bin:/github/home/.local/bin:"$PATH" - west init zephyrproject - cd zephyrproject + # Zephyr setup + apt -y update + west init cd zephyr git checkout ${{ matrix.zephyr_version }} cd .. - west update - west zephyr-export - pip3 install --user -r zephyr/scripts/requirements.txt - cd .. - export TOOLCHAIN_VERSION=${{ matrix.zephyr_sdk }} - export TOOLCHAIN_FILE_NAME=${{ matrix.sdk_filename }} - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$TOOLCHAIN_VERSION/$TOOLCHAIN_FILE_NAME - tar xvf $TOOLCHAIN_FILE_NAME - cd zephyr-sdk-$TOOLCHAIN_VERSION - ./setup.sh -h -t arm-zephyr-eabi -c - cd .. - source zephyr-sdk-$TOOLCHAIN_VERSION/environment-setup-x86_64-pokysdk-linux - export ZEPHYR_TOOLCHAIN_VARIANT=zephyr - export ZEPHYR_SDK_INSTALL_DIR=$(pwd)/zephyr-sdk-$TOOLCHAIN_VERSION - source zephyrproject/zephyr/zephyr-env.sh + west update --narrow # Installing micro-ROS prerequisites pip3 install catkin_pkg lark-parser empy colcon-common-extensions + if [[ ${{ github.ref_name }} == "humble" ]] || [[ ${{ github.head_ref }} == *"humble"* ]]; then + # Use empy version 3.3.4 for Humble + pip3 install empy==3.3.4 + fi + # Build with Serial USB transport - west build -b disco_l475_iot1 micro_ros_zephyr_module -- -DCONFIG_MICROROS_TRANSPORT_SERIAL_USB=y + west build -b disco_l475_iot1 $GITHUB_WORKSPACE/micro_ros_zephyr_module -p -- -DCONFIG_MICROROS_TRANSPORT_SERIAL_USB=y # Build with Serial transport - west build -b disco_l475_iot1 micro_ros_zephyr_module -- -DCONFIG_MICROROS_TRANSPORT_SERIAL=y + west build -b disco_l475_iot1 $GITHUB_WORKSPACE/micro_ros_zephyr_module -p -- -DCONFIG_MICROROS_TRANSPORT_SERIAL=y + diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 859b77d..be5b333 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -10,73 +10,52 @@ on: jobs: - micro_ros_zephyr_module: + nightly_micro_ros_zephyr_module: runs-on: ubuntu-latest - container: ubuntu:22.04 + container: + image: zephyrprojectrtos/ci:v0.26.17 + options: --user root + env: + CMAKE_PREFIX_PATH: /opt/toolchains strategy: fail-fast: false matrix: - zephyr_version: ["zephyr-v3.1.0", "zephyr-v2.7.2"] - distro: ["iron", "humble", "rolling"] + zephyr_version: ["v4.0.0", "v4.1.0"] + distro: ["rolling", "jazzy", "humble"] include: - - distro: iron - branch: iron - distro: rolling branch: rolling + - distro: jazzy + branch: jazzy - distro: humble branch: humble - - zephyr_version: zephyr-v2.7.2 - zephyr_sdk: 0.14.2 - sdk_filename: zephyr-sdk-$TOOLCHAIN_VERSION\_linux-x86_64_minimal.tar.gz - - zephyr_version: zephyr-v3.1.0 - zephyr_sdk: 0.14.2 - sdk_filename: zephyr-sdk-$TOOLCHAIN_VERSION\_linux-x86_64_minimal.tar.gz steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: path: micro_ros_zephyr_module - branch: ${{ matrix.branch }} + ref: ${{ matrix.branch }} - name: Build shell: bash run: | - # Install dependencies - apt update - export DEBIAN_FRONTEND=noninteractive - apt install -y --no-install-recommends wget git cmake ninja-build gperf \ - ccache dfu-util device-tree-compiler wget \ - python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \ - make gcc gcc-multilib g++-multilib libsdl2-dev - - # Install Zephyr environment - pip3 install --user -U west - export PATH=~/.local/bin:/github/home/.local/bin:"$PATH" - west init zephyrproject - cd zephyrproject + # Zephyr setup + apt -y update + west init cd zephyr git checkout ${{ matrix.zephyr_version }} cd .. - west update - west zephyr-export - pip3 install --user -r zephyr/scripts/requirements.txt - cd .. - export TOOLCHAIN_VERSION=${{ matrix.zephyr_sdk }} - export TOOLCHAIN_FILE_NAME=${{ matrix.sdk_filename }} - wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$TOOLCHAIN_VERSION/$TOOLCHAIN_FILE_NAME - tar xvf $TOOLCHAIN_FILE_NAME - cd zephyr-sdk-$TOOLCHAIN_VERSION - ./setup.sh -h -t arm-zephyr-eabi -c - cd .. - source zephyr-sdk-$TOOLCHAIN_VERSION/environment-setup-x86_64-pokysdk-linux - export ZEPHYR_TOOLCHAIN_VARIANT=zephyr - export ZEPHYR_SDK_INSTALL_DIR=$(pwd)/zephyr-sdk-$TOOLCHAIN_VERSION - source zephyrproject/zephyr/zephyr-env.sh + west update --narrow # Installing micro-ROS prerequisites pip3 install catkin_pkg lark-parser empy colcon-common-extensions + if [[ ${{ matrix.branch }} == "humble" ]]; then + # Use empy version 3.3.4 for Humble + pip3 install empy==3.3.4 + fi + # Build with Serial USB transport - west build -b disco_l475_iot1 micro_ros_zephyr_module -- -DCONFIG_MICROROS_TRANSPORT_SERIAL_USB=y + west build -b disco_l475_iot1 $GITHUB_WORKSPACE/micro_ros_zephyr_module -p -- -DCONFIG_MICROROS_TRANSPORT_SERIAL_USB=y # Build with Serial transport - west build -b disco_l475_iot1 micro_ros_zephyr_module -- -DCONFIG_MICROROS_TRANSPORT_SERIAL=y + west build -b disco_l475_iot1 $GITHUB_WORKSPACE/micro_ros_zephyr_module -p -- -DCONFIG_MICROROS_TRANSPORT_SERIAL=y diff --git a/README.md b/README.md index 7b528e3..caf3f26 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # micro-ROS module for Zephyr -This module has been tested in Zephyr RTOS v2.7.0 (SDK 0.14.2) and v3.1.0 (SDK 0.14.2). +This module has been tested in Zephyr RTOS v4.0.0 (SDK 0.16.9-rc3), and v4.1.0 (SDK 0.16.9-rc3), using a docker image based on 'zephyrprojectrtos/zephyr-build:v0.26.17'. ## Dependencies @@ -18,7 +18,7 @@ pip3 install catkin_pkg lark-parser empy colcon-common-extensions For example for `disco_l475_iot1` board: ```bash -west build -b disco_l475_iot1 micro_ros_zephyr_module +west build -b disco_l475_iot1 -p ``` Some configuration parameters can be found using: diff --git a/boards/disco_l475_iot1.conf b/boards/disco_l475_iot1.conf deleted file mode 100644 index fbb1020..0000000 --- a/boards/disco_l475_iot1.conf +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr micro-ROS" -CONFIG_LOG=y -CONFIG_USB_CDC_ACM=y -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_USB_CDC_ACM_RINGBUF_SIZE=2048 diff --git a/boards/disco_l475_iot1.overlay b/boards/disco_l475_iot1.overlay deleted file mode 100644 index 7bd84c9..0000000 --- a/boards/disco_l475_iot1.overlay +++ /dev/null @@ -1,20 +0,0 @@ -/ { - aliases { - uros-serial-port = &usart1; - }; -}; - -&usart1 { - status = "okay"; -}; - -zephyr_udc0: &usbotg_fs { - status = "okay"; -}; - -&zephyr_udc0 { - cdc_acm_uart0: cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; - label = "CDC_ACM_0"; - }; -}; diff --git a/modules/libmicroros/CMakeLists.txt b/modules/libmicroros/CMakeLists.txt index 193524d..4e8c213 100644 --- a/modules/libmicroros/CMakeLists.txt +++ b/modules/libmicroros/CMakeLists.txt @@ -52,10 +52,9 @@ externalproject_add(libmicroros_project BUILD_BYPRODUCTS ${MICROROS_DIR}/libmicroros.a ) -zephyr_library_import(libmicroros ${MICROROS_DIR}/libmicroros.a) +zephyr_link_libraries(${MICROROS_DIR}/libmicroros.a) zephyr_interface_library_named(microros) -add_dependencies(microros libmicroros) add_dependencies(microros libmicroros_project) target_include_directories(microros INTERFACE ${MICROROS_DIR}/include) @@ -96,7 +95,6 @@ zephyr_library_sources( add_dependencies(microros microros_transports) add_dependencies(microros_transports libmicroros_project) -add_dependencies(microros_transports libmicroros) # Cleaning diff --git a/modules/libmicroros/microros_transports/serial-usb/microros_transports.c b/modules/libmicroros/microros_transports/serial-usb/microros_transports.c index 6c2f8b7..289e382 100644 --- a/modules/libmicroros/microros_transports/serial-usb/microros_transports.c +++ b/modules/libmicroros/microros_transports/serial-usb/microros_transports.c @@ -33,7 +33,7 @@ char uart_out_buffer[RING_BUF_SIZE]; struct ring_buf out_ringbuf, in_ringbuf; -static void uart_fifo_callback(const struct device *dev, void *user_data){ +static void uart_fifo_callback(const struct device *dev, void * user_data){ while (uart_irq_update(dev) && uart_irq_is_pending(dev)) { if (uart_irq_rx_ready(dev)) { int recv_len; @@ -64,15 +64,14 @@ static void uart_fifo_callback(const struct device *dev, void *user_data){ } bool zephyr_transport_open(struct uxrCustomTransport * transport){ + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; + int ret; uint32_t baudrate, dtr = 0U; - const struct device *uart_dev; - /* for serial-usb transport we just override the device pointer - * with USB to use the same interface - */ - transport->args = (void *)device_get_binding("CDC_ACM_0"); - if (!transport->args) { + + params->uart_dev = device_get_binding("CDC_ACM_0"); + if (!params->uart_dev) { printk("CDC ACM device not found\n"); return false; } @@ -83,15 +82,13 @@ bool zephyr_transport_open(struct uxrCustomTransport * transport){ return false; } - uart_dev = (const struct device *)transport->args; ring_buf_init(&out_ringbuf, sizeof(uart_out_buffer), uart_out_buffer); ring_buf_init(&in_ringbuf, sizeof(uart_in_buffer), uart_out_buffer); printk("Waiting for agent connection\n"); while (true) { - - uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_DTR, &dtr); + uart_line_ctrl_get(params->uart_dev, UART_LINE_CTRL_DTR, &dtr); if (dtr) { break; } else { @@ -103,12 +100,12 @@ bool zephyr_transport_open(struct uxrCustomTransport * transport){ printk("Serial port connected!\n"); /* They are optional, we use them to test the interrupt endpoint */ - ret = uart_line_ctrl_set(uart_dev, UART_LINE_CTRL_DCD, 1); + ret = uart_line_ctrl_set(params->uart_dev, UART_LINE_CTRL_DCD, 1); if (ret) { printk("Failed to set DCD, ret code %d\n", ret); } - ret = uart_line_ctrl_set(uart_dev, UART_LINE_CTRL_DSR, 1); + ret = uart_line_ctrl_set(params->uart_dev, UART_LINE_CTRL_DSR, 1); if (ret) { printk("Failed to set DSR, ret code %d\n", ret); } @@ -116,33 +113,34 @@ bool zephyr_transport_open(struct uxrCustomTransport * transport){ /* Wait 1 sec for the host to do all settings */ k_busy_wait(1000*1000); - ret = uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); + ret = uart_line_ctrl_get(params->uart_dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); if (ret) { printk("Failed to get baudrate, ret code %d\n", ret); } - uart_irq_callback_set(uart_dev, uart_fifo_callback); + uart_irq_callback_set(params->uart_dev, uart_fifo_callback); /* Enable rx interrupts */ - uart_irq_rx_enable(uart_dev); + uart_irq_rx_enable(params->uart_dev); return true; } bool zephyr_transport_close(struct uxrCustomTransport * transport){ - (void)transport; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; + (void) params; return true; } size_t zephyr_transport_write(struct uxrCustomTransport* transport, const uint8_t * buf, size_t len, uint8_t * err){ - const struct device * uart_dev = (const struct device *) transport->args; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; size_t wrote; wrote = ring_buf_put(&out_ringbuf, buf, len); - - uart_irq_tx_enable(uart_dev); + + uart_irq_tx_enable(params->uart_dev); while (!ring_buf_is_empty(&out_ringbuf)){ k_sleep(K_MSEC(5)); @@ -152,7 +150,7 @@ size_t zephyr_transport_write(struct uxrCustomTransport* transport, const uint8_ } size_t zephyr_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){ - const struct device * uart_dev = (const struct device *) transport->args; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; size_t read = 0; int spent_time = 0; @@ -162,9 +160,9 @@ size_t zephyr_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, spent_time++; } - uart_irq_rx_disable(uart_dev); + uart_irq_rx_disable(params->uart_dev); read = ring_buf_get(&in_ringbuf, buf, len); - uart_irq_rx_enable(uart_dev); + uart_irq_rx_enable(params->uart_dev); return read; } \ No newline at end of file diff --git a/modules/libmicroros/microros_transports/serial-usb/microros_transports.h b/modules/libmicroros/microros_transports/serial-usb/microros_transports.h index 3197c76..ff76070 100644 --- a/modules/libmicroros/microros_transports/serial-usb/microros_transports.h +++ b/modules/libmicroros/microros_transports/serial-usb/microros_transports.h @@ -29,7 +29,13 @@ extern "C" { #endif +typedef struct { + size_t fd; + const struct device *uart_dev; +} zephyr_transport_params_t; + #define MICRO_ROS_FRAMING_REQUIRED true +static zephyr_transport_params_t default_params; bool zephyr_transport_open(struct uxrCustomTransport * transport); bool zephyr_transport_close(struct uxrCustomTransport * transport); diff --git a/modules/libmicroros/microros_transports/serial/microros_transports.c b/modules/libmicroros/microros_transports/serial/microros_transports.c index cb2f372..1aef137 100644 --- a/modules/libmicroros/microros_transports/serial/microros_transports.c +++ b/modules/libmicroros/microros_transports/serial/microros_transports.c @@ -24,6 +24,7 @@ #include #define RING_BUF_SIZE 2048 +#define UART_NODE DT_NODELABEL(usart1) char uart_in_buffer[RING_BUF_SIZE]; char uart_out_buffer[RING_BUF_SIZE]; @@ -49,14 +50,20 @@ static void uart_fifo_callback(const struct device * dev, void * args){ } bool zephyr_transport_open(struct uxrCustomTransport * transport){ - const struct device * uart_dev = (const struct device *) transport->args; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; + + params->uart_dev = DEVICE_DT_GET(UART_NODE); + if (!params->uart_dev) { + printk("Serial device not found\n"); + return false; + } ring_buf_init(&in_ringbuf, sizeof(uart_in_buffer), uart_out_buffer); - uart_irq_callback_set(uart_dev, uart_fifo_callback); + uart_irq_callback_set(params->uart_dev, uart_fifo_callback); /* Enable rx interrupts */ - uart_irq_rx_enable(uart_dev); + uart_irq_rx_enable(params->uart_dev); return true; } @@ -68,18 +75,18 @@ bool zephyr_transport_close(struct uxrCustomTransport * transport){ } size_t zephyr_transport_write(struct uxrCustomTransport* transport, const uint8_t * buf, size_t len, uint8_t * err){ - const struct device * uart_dev = (const struct device *) transport->args; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; for (size_t i = 0; i < len; i++) { - uart_poll_out(uart_dev, buf[i]); + uart_poll_out(params->uart_dev, buf[i]); } return len; } size_t zephyr_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err){ - const struct device * uart_dev = (const struct device *) transport->args; + zephyr_transport_params_t * params = (zephyr_transport_params_t*) transport->args; size_t read = 0; int spent_time = 0; @@ -89,9 +96,9 @@ size_t zephyr_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, spent_time++; } - uart_irq_rx_disable(uart_dev); + uart_irq_rx_disable(params->uart_dev); read = ring_buf_get(&in_ringbuf, buf, len); - uart_irq_rx_enable(uart_dev); + uart_irq_rx_enable(params->uart_dev); return read; } \ No newline at end of file diff --git a/modules/libmicroros/microros_transports/serial/microros_transports.h b/modules/libmicroros/microros_transports/serial/microros_transports.h index 3197c76..8889d47 100644 --- a/modules/libmicroros/microros_transports/serial/microros_transports.h +++ b/modules/libmicroros/microros_transports/serial/microros_transports.h @@ -29,7 +29,13 @@ extern "C" { #endif +typedef struct { + size_t fd; + const struct device * uart_dev; +} zephyr_transport_params_t; + #define MICRO_ROS_FRAMING_REQUIRED true +volatile static zephyr_transport_params_t default_params = {.fd = 1}; bool zephyr_transport_open(struct uxrCustomTransport * transport); bool zephyr_transport_close(struct uxrCustomTransport * transport); diff --git a/prj.conf b/prj.conf index aa11d31..8c8706b 100644 --- a/prj.conf +++ b/prj.conf @@ -1,5 +1,6 @@ CONFIG_GPIO=y CONFIG_MICROROS=y +CONFIG_CPP=y CONFIG_MAIN_STACK_SIZE=25000 CONFIG_MAIN_THREAD_PRIORITY=3 @@ -9,7 +10,6 @@ CONFIG_NEWLIB_LIBC_NANO=n CONFIG_PTHREAD_IPC=n CONFIG_POSIX_API=y -CONFIG_APP_LINK_WITH_POSIX_SUBSYS=y CONFIG_POSIX_CLOCK=y CONFIG_STDOUT_CONSOLE=y diff --git a/src/main.c b/src/main.c index a1d876c..6efe05c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ #include #if ZEPHYR_VERSION_CODE >= ZEPHYR_VERSION(3,1,0) -#include +#include #include #include #include @@ -39,11 +39,11 @@ void timer_callback(rcl_timer_t * timer, int64_t last_call_time) } } -void main(void) +int main(void) { rmw_uros_set_custom_transport( MICRO_ROS_FRAMING_REQUIRED, - (void *) DEVICE_DT_GET(DT_ALIAS(uros_serial_port)), + (void *) &default_params, zephyr_transport_open, zephyr_transport_close, zephyr_transport_write, @@ -91,4 +91,5 @@ void main(void) // free resources RCCHECK(rcl_publisher_fini(&publisher, &node)) RCCHECK(rcl_node_fini(&node)) + return 0; }