NI Linux Real-Time Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

NI Linux RT hardfp

I'm trying to run a closed source executable on my myRIO running NI Linux RT, which is unfortunately compiled using the ARM hardfp libraries.

 

I therefore have three main questions:

  • Is it possible for me to manually install the required ld-linux-armhf.so library? If so what would be the best way of approaching this? Will this not then clash with the OS's use of the floating point registers?
  • If this isn't possible, is there any reason I cannot recompile the whole NI Linux kernel using the hardfp flags? I'm assuming however this will then prevent me using any Labview software, is this correct?
  • Failing this, does there exist any way of redirecting the hardfp calls to the softfp abi in a similar manner to a VM?

Thanks

 

Matt

 

 

 

0 Kudos
Message 1 of 4
(2,635 Views)

Hi Matt,

 

You may want to put the kettle on, this turned into a bit longer of a post than I was expecting.

 

So, yes, in theory you could try to take a NI Linux RT softfloat target and attempt to "multilib" it (similar to what is done for most desktop distributions to support 32-bit and 64-bit programs), making both hardfp and softfp libraries (and their associated loader) available on the same system.

 

The biggest issues are:

  • You'd have to get nice and cozy with OpenEmbedded/Yocto to build the needed infrastructure or you'd have to manually handle the sorts of things that OE/Yocto do automatically for you. In either case, this will require some in-depth knowledge of how Linux systems are constructed and how the loader mechanisms work.
  • If you get something wrong in the setup, you may not know it until you run an application that passes float values (armhf and armsoftfp are basically the same subset of machine code, the only difference being how float variables are passed from one section of code to another.) I've verified that you can trick NI Linux RT targets into running armhf code and it works correctly, even if it uses libraries, so long as there are no function calls that pass floating point values. If it does, you'd be lucky if it crashes (e.g. a function that passes floats and pointers), it may just merrily continue with garbage data instead. I imagine it is for this reason that multilibbing on ARM to enable hardfloat and softfp at the same time is not really done (along with the "settop box" nature of most ARM Linux devices)
    • If you really feel adventurous, you can try to symlink the loader that it's looking for to the one on the system and see if that works, check for the actual name of the loader by using the readelf command in the binutils package

Another option would be to get a reasonable hardfloat ARM image (e.g. one of the ones meant for the RPi or BBB), extract it to the disk (or USB stick, etc.) and chroot into the other image. This will essentially make the shell session that is chroot'd a hardfp environment. The inverse of this is how the LabVIEW support for BBB/RPi2+ works (chrooting into a softfp environment).

 

"But wait", you say, "what kernel are you using? Did you somehow boot the kernel in the other system's OS image?" No, the "hardfp" shell is still using the same kernel as the NI Linux RT system. "Wait! You're using a softfp kernel with a hardfp system‽ Won't that run into the same issues that you mention above‽" No, and here's why: The kernel is always compiled softfp, no matter the tools that you use or the target you build for. There is almost no float math in the kernel (some in some drivers working with hardware that doesn't just provide raw values), and I'm guessing it cuts out a major support headache (different compile options, different calling convention, essentially a different architecture) for minimal-to-no performance loss. The fact is that there's no direct calls from userspace to kernelspace (or back) that pass floats directly. All interactions to kernelspace load integers (syscall number) and pointers (values passed) and trigger a transition to kernelspace, and the kernel can then pull the values that it needs.

0 Kudos
Message 2 of 4
(2,612 Views)

Hi Brad,

 

Thank you for such an in-depth response!

 

Not being a Linux expert, the chroot option sounds superior. However, I am now also needing to use an armhf compiled shared library in my VI, which I'm calling using a call library function block. Since chroot applies to the current running process, am I right that it won't be possible to use this approach to call a armhf shared library, as this would result in the whole labview process accessing the wrong libraries? (I know it isn't possible to link like this normally, but I'm unsure as to how exactly shared library linking works under the hood in labview)

 

Alternatively to chroot, I'm wondering if it is possible for me to manually copy /lib from an RPi image into my target as /lib_armhf, and then use the gcc -rpath linker option or the patchelf utility to hardcode my shared library to use this alternative loader and libraries? I am however currently trying this approach with no success so far, so if there is a fundamental flaw with this concept that I'm missing I'd be happy to hear it!

 

Thanks again

 

Matt

0 Kudos
Message 3 of 4
(2,572 Views)

The chroot option won't work for needing to call a shared library from LabVIEW RT (which is softfp). It will run into the issues that I described earlier (namely, the code generated around the CLFN will be expecting the float arguments to be passed to functions in integer registers, not in the FPU registers, while the library will be expecting float arguments to be passed in those FPU registers).

 

Whole-sale copying /lib (and /usr/lib) from a RPi OS image to a different location on disk and attempting to patch-up (after the fact) would be a tough row to hoe, and even if you did it correctly, you'd be violating the fundamental aim (disallowing cross-ABI calls between binaries). The fact of the matter is that you have two binaries that cannot change ABI (LabVIEW RT and this library), you cannot recompile LabVIEW RT to be a different ABI, and I assume you cannot do that for the library either.

 

You have two options:

  1. If there are no floats, doubles, etc. in the calling ABI for the library (that is going to be called from LabVIEW RT), just use it. If it has dependencies that it loads as well (that are not already on your system), make sure that they are on the library ldcache search path (described by /etc/ld.so.conf). This approach is risky, may fail, but it fairly easy to try out.
  2. The safer, more laborious route would be to de-couple the library from being directly called by LabVIEW RT by means of some sort of an RPC (or general server/client) type of mechanism, the server running in the chroot, the client being the library that is called from LabVIEW RT.
0 Kudos
Message 4 of 4
(2,558 Views)