Ubilinux on the Intel Galileo: Tmrh20's RF24 Library for nRF24L01+ radios (Part III)

[Deprecated - Updated post is here]

The saga continues.
So, I did some googling around, and found a blog where a guy recommended installing a tool called valgrind. Apparently valgrind is a memory leak detector amongst many other things. Was a bit skeptical but I went right ahead, apt-get install'd valgrind and then invoked my new program under valgrind as follows;

valgrind ./program

After about a minute or two, valgrind shows me an error at some memory location, explaining that it encountered an illegal/invalid instruction at that location and gave me two reasons why that could happen. Following the...stack trace....it printed, the problem seemed to be coming from code in the librf24-bcm.so file. Strange.
After some more Google-fu, which eventually led me to Wikipedia, I found that the Quark X1000 SoC used on the Galileo did not support SSE or MMX instructions, and was instruction-set architecture compatible with the i586 family. I thought about it, and it seemed that clang was emitting machine code utilizing these special instructions or machine code not tailored for the i586. Some more Google-fu showed me that I could turn off MMX instructions by appending -mno-mmx to the clang invocation, and I could turn off SSE instructions by appending -mno-sse to the clang invocation. I could also force it to target the i586 ISA by appending -march=i586 to the invocation.

Essentially, I had to recompile the RF24 library itself, but ensure that I used these compiler flags. Editing the Makefile once again, in the section starting with "ifeq "$(RF24_MRAA)" "1", I appended the following lines:

CCFLAGS=-mno-sse -mno-mmx -march=i586

Then recompiled the library. Once that was done, I tried to recompile my own app, which worked fine. When I came to run it, it seemed to work! There was a console prompt asking me which mode I wanted this device to be in: Pong-back or Ping_out. Once I entered the choice, I got the same "illegal instruction" error. Damn!

Running the program under valgrind again showed me that the error this time was in libmraa.so this time, which would mean that I would need to recompile MRAA itself, using these newly discovered -mno-sse -mno-mmx -march=i586 flags. But MRAA compilation used Cmake to manage the Makefiles, so I had to find a way of telling Cmake to include those flags. As Google would have it, I found that appending -DCMAKE_C_FLAGS=-mno-sse -mno-mmx -march=i586 -DCMAKE_CXX_FLAGS=-mno-sse -mno-mmx -march=i586 to the cmake invocation would do just that, hence the full cmake invocation to compile MRAA for the Galileo would become:

cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS=-mno-sse -mno-mmx -march=i586 -DCMAKE_CXX_FLAGS=-mno-sse -mno-mmx -march=i586 -DBUILDSWIGNODE=off -DBUILDSWIGPYTHON=off

That completed successfully, after which I ran make and then make install. Once this was done, I went and recompiled the RF24 library once again to link against the newly-compiled MRAA shared library, then recompiled my own app against the once-again-recompiled RF24 library. Actually before recompiling the app, I edited the gettingstarted.cpp file and changed the radio number to 1 - to solve addressing issues as the Arduino version (which used radio number = 0). In addition, I recompiled my own app with the -mno-sse -mno-mmx -march-i586 flags as well.
I then uploaded the getting started sketch to the Arduino, and opened the Serial Monitor. Next, I ran the program on the Galileo, and selected the "Ping Out" role, and voila! The Arduino started printing out messages about once a second, and the Galileo was also printing out messages that went;

Got response 3353113565, round-trip delay: 10
Got response 3353114570, round-trip delay: 11

And so on and so forth.

Essentially, I got the RF24 library by Tmrh20 running on the Galileo running the Ubilinux distro. That was acheived by compiling MRAA with clang and certain compiler flags targetting the Quark X1000 SoC, making a few changes to the RF24 Makefile (to target clang and set the -mno-sse -mno-mmx -march=i586 options) and Rf24_config.h files (#define MRAA and #define LINUX) then building the RF24 shared library. Finally, you can then compile your own app using the same compile flags (-mno-sse -mno-mmx -march=i586) and link it against the RF24 shared library. It would probably be easier if you make install'd the RF24 library (you wouldn't need to tinker with any file in /etc/ld.so.conf.d) but that's left as an exercise for you!

As for me, I'm going to play with the nRF24 radios, using them to communicate between the Arduino and the Galileo board. I hope to put a better-structured set of posts together someday, so we'll see.
Hope to see you soon. Ta-ta!


  1. That should be CFLAGS not CCFLAGS. Thanks for the guide. I was able to get mine to work following this with just a few modifications. You rock!


Post a Comment

Popular posts from this blog

Enabling SPI1 on the Raspberry Pi B+/Zero/2/3

Bitbanging SPI on the Raspberry Pi (via spi-gpio)

Getting Started with Logic Analyzers and Pulseview