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

Support RTEMS #397

Closed
roncapat opened this issue Oct 9, 2021 · 31 comments
Closed

Support RTEMS #397

roncapat opened this issue Oct 9, 2021 · 31 comments
Labels
enhancement New feature or request

Comments

@roncapat
Copy link

roncapat commented Oct 9, 2021

It would be interesting to use micro-ROS on RTEMS (The Real-Time Executive for Multiprocessor Systems).

It is an RTOS used in space applications.
It offers POSIX interface.
A simple and cheap SBC like a BeagleBone Black would be sufficient to make tests on hardware (but everything can be done also virtually).

For now, I do not have the time to try alone,
Of course, if I ever find the time I will try on my own and share PRs if it's ok.

@roncapat
Copy link
Author

roncapat commented Oct 9, 2021

I started to compile against an old RTEMS toolchain of mine, since it was ready on my PC.

rtems_toolchain.cmake

set(RTEMS_ROOT_PATH             "/mnt/sdb/rtems")
set(RTEMS_TOOLS_INSTALL_DIR     "${RTEMS_ROOT_PATH}/5")
set(RTEMS_TOOLS_BSP_LIB_DIR     "${RTEMS_ROOT_PATH}/5/sparc-rtems5/lib")
set(RTEMS_KERNEL_INSTALL_DIR    "${RTEMS_ROOT_PATH}/5/sparc-rtems5/erc32")
set(RTEMS_KERNEL_BSP_LIB_DIR    "${RTEMS_ROOT_PATH}/5/sparc-rtems5/erc32/lib")

set(ENV{PATH} "${RTEMS_TOOLS_INSTALL_DIR}/bin:$ENV{PATH}")
set(RTEMS_TOOLS_BSP_INCLUDE_DIR       "${RTEMS_ROOT_PATH}/5/sparc-rtems5/include")
set(RTEMS_KERNEL_BSP_INCLUDE_DIR      "${RTEMS_KERNEL_BSP_LIB_DIR}/include")
set(RTEMS_COMPILE_OPTIONS             "-B${RTEMS_KERNEL_BSP_LIB_DIR} -B${RTEMS_TOOLS_BSP_LIB_DIR} -specs bsp_specs -qrtems -mcpu=cypress")

set(CMAKE_SYSTEM_NAME         Generic)
set(CMAKE_SYSTEM_PROCESSOR    sparc)

set(CMAKE_C_COMPILER "sparc-rtems5-gcc")
set(CMAKE_CXX_COMPILER "sparc-rtems5-g++")

include_directories(BEFORE ${RTEMS_TOOLS_BSP_INCLUDE_DIR}                         
                           ${RTEMS_KERNEL_BSP_INCLUDE_DIR})

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

rtems.colcon.meta

{
    "names": {
        "tracetools": {
            "cmake-args": [
                "-DTRACETOOLS_DISABLED=ON",
                "-DTRACETOOLS_STATUS_CHECKING_TOOL=OFF"
            ]
        },
        "rosidl_typesupport": {
            "cmake-args": [
                "-DROSIDL_TYPESUPPORT_SINGLE_TYPESUPPORT=ON"
            ]
        },
        "rcl": {
            "cmake-args": [
                "-DBUILD_TESTING=OFF",
                "-DRCL_COMMAND_LINE_ENABLED=OFF",
                "-DRCL_LOGGING_ENABLED=OFF"
            ]
        }, 
        "rcutils": {
            "cmake-args": [
                "-DENABLE_TESTING=OFF",
                "-DRCUTILS_NO_FILESYSTEM=ON",
                "-DRCUTILS_NO_THREAD_SUPPORT=ON",
                "-DRCUTILS_AVOID_DYNAMIC_ALLOCATION=ON"
            ]
        },
        "microxrcedds_client": {
            "cmake-args": [
                "-DUCLIENT_PIC=OFF",
                "-DUCLIENT_PLATFORM_POSIX=ON",
                "-DUCLIENT_PROFILE_UDP=OFF",
                "-DUCLIENT_PROFILE_TCP=OFF",
                "-DUCLIENT_PROFILE_DISCOVERY=OFF",
                "-DUCLIENT_PROFILE_SERIAL=ON",
                "-DUCLIENT_PROFILE_STREAM_FRAMING=ON",
                "-DUCLIENT_PROFILE_CUSTOM_TRANSPORT=OFF"
            ]
        },
        "rmw_microxrcedds": {
            "cmake-args": [
                "-DRMW_UXRCE_MAX_NODES=1",
                "-DRMW_UXRCE_MAX_PUBLISHERS=1",
                "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=1",
                "-DRMW_UXRCE_MAX_SERVICES=1",
                "-DRMW_UXRCE_MAX_CLIENTS=1",
                "-DRMW_UXRCE_MAX_HISTORY=4",
                "-DRMW_UXRCE_TRANSPORT=serial"
            ]
        }
    }
}

In my ros2_workspace:

ros2 run micro_ros_setup create_firmware_ws.sh generate_lib
ros2 run micro_ros_setup build_firmware.sh $(pwd)/src/micro_ros_setup/config/generate_lib/generic/rtems_toolchain.cmake $(pwd)/src/micro_ros_setup/config/generate_lib/generic/rtems-colcon.meta

Compilation goes on without critical failures. I met only a bug in:

mcu_ws/uros/rmw_microxrcedds/rmw_microxrcedds_c/src/memory.c

where #include <memory.h> should be substituted with #include "memory.h" to let the compiler use:

mcu_ws/uros/rmw_microxrcedds/rmw_microxrcedds_c/src/memory.h instead of something else in the include path.

@roncapat
Copy link
Author

roncapat commented Oct 9, 2021

A lot of warnings though. This one occurs at every package.

CMake Warning at /mnt/sdb/microros_ws/firmware/mcu_ws/install/share/rcutils/cmake/ament_cmake_export_libraries-extras.cmake:116 (message):
  Package 'rcutils' exports library 'dl' which couldn't be found

This annoying warning can be suppressed by commenting out the following line:

ament_export_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})

in firmware/mcu_ws/uros/rcutils/CMakeLists.txt

@roncapat
Copy link
Author

roncapat commented Oct 9, 2021

Is there a list of all the definitions in colcon.meta?

@roncapat
Copy link
Author

I discovered that no matter if in your custom toolchain you add a line such:

set(CMAKE_DL_LIBS "-lrtemscpu") # contains dlopen() family of symbols in RTEMS 

the rcutils CMake will always have dl as ${CMAKE_DL_LIBS}. Like if the override would not work correctly.

@roncapat
Copy link
Author

Some updates:

rtems-toolchain.cmake

set(RTEMS_ROOT_PATH             "/mnt/sdb/rtems")
set(RTEMS_TOOLS_INSTALL_DIR     "${RTEMS_ROOT_PATH}/5")
set(RTEMS_TOOLS_BSP_LIB_DIR     "${RTEMS_ROOT_PATH}/5/arm-rtems5/lib")
set(RTEMS_KERNEL_INSTALL_DIR    "${RTEMS_ROOT_PATH}/5/arm-rtems5/beagleboneblack")
set(RTEMS_KERNEL_BSP_LIB_DIR    "${RTEMS_ROOT_PATH}/5/arm-rtems5/beagleboneblack/lib")

set(ENV{PATH} "${RTEMS_TOOLS_INSTALL_DIR}/bin:$ENV{PATH}")
set(RTEMS_TOOLS_BSP_INCLUDE_DIR       "${RTEMS_ROOT_PATH}/5/arm-rtems5/include")
set(RTEMS_KERNEL_BSP_INCLUDE_DIR      "${RTEMS_KERNEL_BSP_LIB_DIR}/include")
set(RTEMS_COMPILE_OPTIONS             "-B${RTEMS_KERNEL_BSP_LIB_DIR} -B${RTEMS_TOOLS_BSP_LIB_DIR} -specs bsp_specs -qrtems -mcpu=cortex-a8")

set(CMAKE_SYSTEM_NAME         Generic)
set(CMAKE_SYSTEM_PROCESSOR    arm)

set(CMAKE_C_COMPILER "arm-rtems5-gcc")
set(CMAKE_CXX_COMPILER "arm-rtems5-g++")
set(CMAKE_DL_LIBS "-lrtemscpu")

set(CMAKE_CXX_FLAGS "${RTEMS_COMPILE_OPTIONS} -g -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable")
set(CMAKE_C_FLAGS "${RTEMS_COMPILE_OPTIONS} -g -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable")

include_directories(BEFORE ${RTEMS_TOOLS_BSP_INCLUDE_DIR}                         
                           ${RTEMS_KERNEL_BSP_INCLUDE_DIR})

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

rtems-colcon.meta

{
    "names": {
        "tracetools": {
            "cmake-args": [
                "-DTRACETOOLS_DISABLED=ON",
                "-DTRACETOOLS_STATUS_CHECKING_TOOL=OFF"
            ]
        },
        "rosidl_typesupport": {
            "cmake-args": [
                "-DROSIDL_TYPESUPPORT_SINGLE_TYPESUPPORT=ON"
            ]
        },
        "rcl": {
            "cmake-args": [
                "-DBUILD_TESTING=OFF",
                "-DRCL_COMMAND_LINE_ENABLED=OFF",
                "-DRCL_LOGGING_ENABLED=OFF"
            ]
        }, 
        "rcutils": {
            "cmake-args": [
                "-DENABLE_TESTING=OFF",
                "-DRCUTILS_NO_FILESYSTEM=ON",
                "-DRCUTILS_NO_THREAD_SUPPORT=OFF",
                "-DRCUTILS_AVOID_DYNAMIC_ALLOCATION=ON"
            ]
        },
        "microxrcedds_client": {
            "cmake-args": [
                "-DUCLIENT_PIC=OFF",
                "-DUCLIENT_PLATFORM_POSIX=ON",
                "-DUCLIENT_PROFILE_UDP=OFF",
                "-DUCLIENT_PROFILE_TCP=OFF",
                "-DUCLIENT_PROFILE_DISCOVERY=OFF",
                "-DUCLIENT_PROFILE_SERIAL=ON",
                "-DUCLIENT_PROFILE_STREAM_FRAMING=ON",
                "-DUCLIENT_PROFILE_CUSTOM_TRANSPORT=OFF"
            ]
        },
        "rmw_microxrcedds": {
            "cmake-args": [
                "-DRMW_UXRCE_MAX_NODES=1",
                "-DRMW_UXRCE_MAX_PUBLISHERS=1",
                "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=1",
                "-DRMW_UXRCE_MAX_SERVICES=1",
                "-DRMW_UXRCE_MAX_CLIENTS=1",
                "-DRMW_UXRCE_MAX_HISTORY=4",
                "-DRMW_UXRCE_TRANSPORT=serial"
            ]
        }
    }
}

I commented out:

ament_export_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})

in rcutils/CMakeLists.txt and suppressed in the toolchain some unused variable warnings to reduce the noise at the bare minimum. Of course those warnings should be later addressed in the various project by correct code tweaks, but this is not the scope of my work now.

Here is the only notable warning/error popping out of my build step:

--- stderr: micro_ros_utilities                                                                                      
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c: In function 'print_type_info':
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:93:5: warning: implicit declaration of function 'snprintf' [-Wimplicit-function-declaration]
     snprintf(
     ^~~~~~~~
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:93:5: warning: incompatible implicit declaration of built-in function 'snprintf'
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:93:5: note: include '<stdio.h>' or provide a declaration of 'snprintf'
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:94:74: warning: format '%ld' expects argument of type 'long int', but argument 8 has type 'size_t {aka const unsigned int}' [-Wformat=]
       buffer, sizeof(buffer), "%sIntrospection for %s/%s - %d members, %ld B\n",
                                                                        ~~^
                                                                        %d
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:99:7:
       members->size_of_
       ~~~~~~~~~~~~~~~~~                                                   
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:115:5: warning: incompatible implicit declaration of built-in function 'snprintf'
     snprintf(
     ^~~~~~~~
/mnt/sdb/microros_ws/firmware/mcu_ws/uros/micro_ros_utilities/src/type_utilities.c:115:5: note: include '<stdio.h>' or provide a declaration of 'snprintf'
---

@roncapat
Copy link
Author

I opended some PRs to fix the warnings.

Next step is waiting to retrieve my Beaglebone Black (which now I don't have with me, but it will be again sometime in the following weeks) and start some tests.

@roncapat
Copy link
Author

TODOs (suggestions welcomed):

  • build a sample application with micro-ros targeting RTEMS BeagleBone Black
  • deploy the application
  • get RTEMS boot correctly
  • tune rtems-colcon.meta
  • ensure everything works

In particular, one doubt of mine is how to specify which serial/network port to use on the board to the micro-ros library.

Hoping it is somewhere in the documentation. If anyone can pinpoint me, it would be awesome.

@joelsherrill
Copy link

Are there any tests which don't require networking and just check basic services to start with? And I would recommend trying arm/zynq on qemu first. If you need a example RTEMS configuration and initialization that sets things up and then calls main(), just ask and I'll email it to you privately

@roncapat
Copy link
Author

I believe the basic setup could be a RTEMS application with 1 task and 1 micro-ROS publisher.
Yes, I need to check if with my pre-existing setup I can already run a RTEMS-only demo in qemu, just to be sure that everything works before start breaking stuff.

@roncapat
Copy link
Author

roncapat commented Oct 11, 2021

In parallel with making myself a new RTEMS environment (with the goal to execute some default tests in the emulator before starting to add micro-ROS in the mix), I'm reading more about micro-ROS.

I have some questions in my mind, but the first one is:
do you believe or know wether it will be necessary to write some specific code to adapt to this RTOS, or everything shoud work out of the box because the target RTOS is a POSIX system? Do you have a list of steps for things to check?

EDIT: let me rephrase that: using generate_lib, is there any target-specific source code implementation needed to support micro-ROS, or I just need to use its API as normal when writing a task of my RTOS image?

@roncapat
Copy link
Author

I tried to dig in the source code, following the source of an example:
https://github.com/micro-ROS/freertos_apps/blob/foxy/apps/ping_pong/app.c
and for what I've seen up to now, it's all about allocation and initialisation of structures until the rclc_executor_spin_some() is called. In an RTEMS application. Since micro-ROS seems to not open autonomously other threads/tasks/processes, but you must explicitly spin the executor in foreground in a task you write and schedule, I think the effort to get to aminimal demo like the ping-pong one should not be very high and aside for the task, maybe no target-specific code for the adaptation of micro-ROS onto RTEMS should be needed.

@joelsherrill
Copy link

I have some questions in my mind, but the first one is: do you believe or know wether it will be necessary to write some specific code to adapt to this RTOS, or everything shoud work out of the box because the target RTOS is a POSIX system? Do you have a list of steps for things to check?

I can't tell if this is a micro-ROS or RTEMS question. I can't imagine ROS needs anything from POSIX that RTEMS does not have. We have this guide in our documentation set (https://docs.rtems.org/branches/master/posix-compliance/index.html) which details how RTEMS aligns against various C and POSIX based standards.

EDIT: let me rephrase that: using generate_lib, is there any target-specific source code implementation needed to support micro-ROS, or I just need to use its API as normal when writing a task of my RTOS image?

If a package has a POSIX port which is geared to embedded environments (e.g. doesn't use fork/exec, graphics, etc.), then it often just compiles for RTEMS. The issues that must be addressed are RTEMS initialization and configuration and possibly contents of the initial filesystem.

@roncapat
Copy link
Author

Thank you @joelsherrill for your answers! Yes, I followed the source code pointed and used by the demo but never found fork/exec. When I have time, I'll also do a keyword based research around the codebase just as an additional check.

@roncapat
Copy link
Author

Hello everyone, finally I got a clean RTEMS 5.1 erc32 BSP (sparc) built on my PC.
All standard tests ran in the simulator, so I was ready to start fiddling with microROS in a RTEMS app.

A year ago, I wrote this simple CMake template fort RTEMS.
I made it compile for erc32 and run with the simulator. Everything OK.

Now I started porting the ping-pong microROS app.
Here is the source pingpongport_1.zip.

I started copy-pasting some code from freeRTOS ping-pong example and up to now, the compiler errors are:

[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /mnt/sdb/rtems_master/workspace/microROS/build --config Debug --target all -j 10 --
[build] [1/1 100% :: 0.132] Linking CXX executable HELLO
[build] FAILED: HELLO 
[build] : && /mnt/sdb/rtems_master/rtems/5/bin/sparc-rtems5-g++  -B/mnt/sdb/rtems_master/rtems/5/sparc-rtems5/erc32/lib -B/mnt/sdb/rtems_master/rtems/5/sparc-rtems5/lib -specs bsp_specs -qrtems -mcpu=cypress -g   CMakeFiles/HELLO.dir/example.cpp.obj  -o HELLO -L/mnt/sdb/microros_ws/firmware/build -lmicroros && :
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/build/libmicroros.a(libmicrocdr-array.c.obj): in function `ucdr_serialize_array_uint16_t':
[build] /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:176: undefined reference to `_GLOBAL_OFFSET_TABLE_'
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:176: undefined reference to `_GLOBAL_OFFSET_TABLE_'
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/build/libmicroros.a(libmicrocdr-array.c.obj): in function `ucdr_serialize_array_uint32_t':
[build] /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:177: undefined reference to `_GLOBAL_OFFSET_TABLE_'
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:177: undefined reference to `_GLOBAL_OFFSET_TABLE_'
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/build/libmicroros.a(libmicrocdr-array.c.obj): in function `ucdr_serialize_array_uint64_t':
[build] /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:178: undefined reference to `_GLOBAL_OFFSET_TABLE_'
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/build/libmicroros.a(libmicrocdr-array.c.obj):/mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-CDR/src/c/types/array.c:178: more undefined references to `_GLOBAL_OFFSET_TABLE_' follow
[build] /mnt/sdb/rtems_master/rtems/5/lib/gcc/sparc-rtems5/7.5.0/../../../../sparc-rtems5/bin/ld: /mnt/sdb/microros_ws/firmware/build/libmicroros.a(libmicroxrcedds_client-serial_transport_posix.c.obj): in function `uxr_read_serial_data_platform':
[build] /mnt/sdb/microros_ws/firmware/mcu_ws/eProsima/Micro-XRCE-DDS-Client/src/c/profile/transport/serial/serial_transport_posix.c:64: undefined reference to `poll'
[build] collect2: error: ld returned 1 exit status
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1

In practice, two problems up to now:

  • undefined reference to `GLOBAL_OFFSET_TABLE'
  • undefined reference to `poll'

I suspect the second one is related to the simulator not having a serial port implemented, so I may fix it changing microROS build configuration to use network instead of serial port. But the first issue is the most critical IMHO, and I don't know how to proceed. Any help?

@roncapat
Copy link
Author

Seems that adding to rtems-colcon.meta the following:

"microcdr": {
            "cmake-args": [
                "-DUCDR_PIC=OFF"
            ]
        },

solved the GLOBAL_OFFSET_TABLE problem. Now I have the issue with the unimpemented poll for serial ports in erc32 architecture (sounds to me this is the core of the issue) and going on adding other code of the ping-pong demo to my RTEMS app until everything can be tested and demonstrated.

@roncapat
Copy link
Author

roncapat commented Oct 17, 2021

Seems that RTEMS deliberately does not support poll() call.

https://docs.rtems.org/branches/master/posix-compliance/posix-compliance.html

https://docs.rtems.org/releases/rtems-docs-4.11.1/bsp-howto/console.html

RTEMS relies on termios. I need to investigate how to maybe offer an alternative to the POSIX implementation
Micro-XRCE-DDS-Client/src/c/profile/transport/serial/serial_transport_posix.c

@roncapat
Copy link
Author

Another round of updates:

I read the sources and found that for now the simplest way to get to a minimal demo is to use UDP transport with the UCLIENT_PLATFORM_POSIX_POLL flag set. There is a dedicated UDB transport implementation for POSIX platforms without poll(). This is not entirely true for TCP and SERIAL transports, but I'll dig into that later.
Here is my current toolchain, Colcon meta, ping-pong source and build script.

microros_build_conf_2.zip
pingpongport_2.zip

It builds. Now the "hard" part is to test it.

@roncapat
Copy link
Author

Are there any tests which don't require networking and just check basic services to start with? And I would recommend trying arm/zynq on qemu first. If you need a example RTEMS configuration and initialization that sets things up and then calls main(), just ask and I'll email it to you privately

Can you give me some help about what you are saying?

  • a sample app source code
  • a sample qemu command to run the example

Is qemu helpful for testing also tcp/udp and uarts? Is it possible? Do you have some demo code for interface configuration?

@joelsherrill
Copy link

Email me at joel AT rtems dot org and I will email you back a quick start network example for zynq qemu that should help you. If you don't initialize the network stack, then there is no networking.

@roncapat
Copy link
Author

roncapat commented Oct 19, 2021

This branch (https://github.com/roncapat/Micro-XRCE-DDS-Client/tree/foxy) adds a TCP/UDP implementation suitable for RTEMS. It is a clean POSIX using select() call instead of poll(). I will not open a PR until I see it run on RTEMS and not only build correctly.

@roncapat
Copy link
Author

roncapat commented Nov 7, 2021

@joelsherrill I wrote to you by email but sadly no response... Today I set up my beaglebone black and now I'm stuck at the same point of setting up networking. Could you send me the example at roncapat@gmail.com ? It would be very helpful for me.

@joelsherrill
Copy link

@roncapat Not sure what happened. I don't see any email from you about this. But I went ahead and sent it. Poke me if you don't get it.

@roncapat
Copy link
Author

roncapat commented Nov 7, 2021

Thank you so much! Hope to share some project updates before Christmas :)

@roncapat
Copy link
Author

roncapat commented Nov 13, 2021

Working again on the subject.

This time I'm here to share a build issue related to glibc 2.46.

On my system (Ubuntu 20.04) I have sb-set-builder failing with the following, uninformative last line:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 78: ordinal not in range(128)
Adding --log /path/to/logfile to the command line helps to get insights on what happened:

CC       libgio_2_0_la-gdbuserror.lo
../../glib-2.46.2/gio/gdbusauth.c: In function ‘_g_dbus_auth_run_server’:
../../glib-2.46.2/gio/gdbusauth.c:1295:11: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
 1295 |           debug_print ("SERVER: WaitingForBegin, read '%s'", line);
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  CC       libgio_2_0_la-gdbusconnection.lo
  CC       libgio_2_0_la-gdbusmessage.lo
  CC       libgio_2_0_la-gdbusnameowning.lo
cc1: some warnings being treated as errors
make[4]: *** [Makefile:3624: libgio_2_0_la-gdbusauth.lo] Errore 1
make[4]: *** Attesa per i processi non terminati....
../../glib-2.46.2/gio/gdbusmessage.c: In function ‘g_dbus_message_to_blob’:
../../glib-2.46.2/gio/gdbusmessage.c:2698:30: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
 2698 |       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

On the internet, I found only this reference to a simple patch to use whenever host GCC is version 9. However, I have GCC 8 as host compiler and GCC 7.5 as ARM compiler from RSB tools.

I tried to apply manually the patch to the source files and rebuild but files are probably being overwritten. Anyone has the solution to trigger a sb-set-builder rebuild without overwriting source files?

EDIT: more readable patch but not directly applicable.

Patches can be added to the build process in file rtems-source-builder/bare/config/devel/glib-2.46.2-1.cfg. I'll try to produce and apply a suitable patch.

EDIT 2: SOLVED
This Diff Gist has been crafted by me to solve the compilation issues.

In rtems-source-builder/bare/config/devel/glib-2.46.2-1.cfg just add the line

%patch add glib https://gist.githubusercontent.com/roncapat/34eb82ece80ac26fd290a50dc7e85219/raw/247750ad17c31b26ef31af909fbcac05e57f71bd/glibc_2.46-2.1_rtems_5_rsb.patch

after the last %patch or %hash directive and then re-run the sb-set-builder

@roncapat
Copy link
Author

roncapat commented Nov 13, 2021

Another error while trying to build devel/qemu4:

/usr/bin/ld: linux-user/syscall.o: in function `do_syscall1':
/mnt/sdb/rtems-work/rtems-source-builder/bare/build/qemu-4.1.0-x86_64-linux-gnu-1/qemu-4.1.0/linux-user/syscall.c:7660: undefined reference to `stime'

the proper fix should be this one. Trying to follow the same patching logic of the glibc problem.

EDIT: SOLVED
This Diff Gist has been crafted by me to solve the compilation issues.

In rtems-source-builder/bare/config/devel/qemu4-git-1.cfg just add the line

%patch add qemu https://gist.githubusercontent.com/roncapat/34eb82ece80ac26fd290a50dc7e85219/raw/9445c0a954e92d3323596c51b1958c7be38b1cb4/qemu_4.10_rtems_5_rsb.patch

after the last %patch or %hash directive and then re-run the sb-set-builder

EDIT 2:
The patches are being reviewed by RTEMS developers.
https://devel.rtems.org/ticket/4561
https://lists.rtems.org/pipermail/devel/2021-December/070090.html

@roncapat
Copy link
Author

@joelsherrill I think I got to a good point. The task passes all allocations for the DDS, and now the application fails to establish a qemu-outgoing TCP connection to my local host. In fact, the connect() call fails and I receive no handshake on host side. Do you have hints on how to configure gateway or other parameters for outgoing connections from RTEMS app in qemu?

@roncapat
Copy link
Author

connect() from RTEMS QEMU guest tries to connect to microROS Agent on the TCP host port 8888. (127.0.0.1:8888) but returns EADDRNOTAVAIL, when using QEMU SLIRP which by default should allow outgoing packets to 127.0.0.1. RTEMS is configured to use DHCP, as Joel told me to do in his tutorial.

Any suggestions about how to proceed?

@roncapat
Copy link
Author

roncapat commented Nov 14, 2021

Aaaand: IT WORKS!

PingPong example ran successfully on my machine after a very long weekend.

First of all, before forgetting it forever, here is what I found useful to set a tap network between host and qemu:

# For Network Bridging/TAP
# Set permissions of tun device
chown root.users /dev/net/tun 
chmod g+rw /dev/net/tun

#Add a bridge, add eth0
brctl addbr br0
ifconfig eth0 0.0.0.0 promisc
brctl addif br0 eth0
dhclient br0

# Create tap0
tunctl -t tap0 -u username #replace username by your username

# Enable tap0
brctl addif br0 tap0
ifconfig tap0 up

I used qemu from rtems-libbsd. My current command line is:

qemu-system-arm \
-no-reboot \
-serial null -serial mon:stdio \
-net tap,ifname=

tap0 -net nic,model=cadence_gem,macaddr=0e:b0:ba:5e:ba:11 \
-nographic \
-M xilinx-zynq-a9 -m 256M \
-kernel <<<RTEMS exe file>>>

For now, the application connects to the host and set ups correctly all publishers and subscribers. The timer ticks every 2 secs and published a ping message, but unfortunately I can't see it while ros2 topic echo /microROS/ping.

EDIT: the communication works for the first 4 PINGs. After them, seems like the timer is called but the actual publication of the message is not happening anymore.

microros_build_conf_3.zip
pingpongport_3.zip

@roncapat
Copy link
Author

Solved the bug. It was an issue on host->target communication, where the custom code for the DDS failed to poll presence of incoming data. Seems I was not resetting the FD_SET prior to calling select(). Now that everything works well, I do some cleanups and open a PR for the DDS Client.

@roncapat
Copy link
Author

If possible, I'd keep this Issue open. Since support was merged, now the next step would be to find a way to add scripting support for RTEMS build in this repo. When I will have more time I'll give it a try.

@roncapat
Copy link
Author

roncapat commented Dec 3, 2021

Rapid note about testing serial transport with QEMU:

command line:

qemu-system-arm \
-no-reboot \
-serial pty \
-serial mon:stdio \
-nographic \
-M xilinx-zynq-a9 \
-m 256M \
-kernel <<<RTEMS exe file>>>

When launched, a message like this is printed:

char device redirected to /dev/pts/3 (label serial0)

this means that on your host /dev/pts/3 is the port for the micro_ros_agent, while on RTEMS guest side the UART is /dev/ttyS0. Thus, in colcon.meta you have to configure rmw_microxrcedds with "-DRMW_UXRCE_DEFAULT_SERIAL_DEVICE=/dev/ttyS0".

Launch the micro_ros_agent with command line:

ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/pts/3

and only then you can launch your RTEMS mros application.

@pablogs9 pablogs9 added the enhancement New feature or request label Jan 28, 2022
@roncapat roncapat closed this as completed Apr 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants