Cross-compiling ARM ASM on the Mac for the Raspberry Pi

I’ve posted recently about my experience learning some ARM assembly, and in particular, attempting to develop a simple sorting algorithm. Initially I had just been using Atom and TextMate editors on my Mac and then ftp’ing the source over to the Pi to compile and run, but I had got to a point where I realized this wasn’t going to cut it for working on anything slightly larger, so I started looking at getting Eclipse C++ working with cross compiler toolchains (cross compiling allows you to compile code on one hardware architecture type to run on another)

I actually looked into getting this working on Windows several months back, but I hadn’t used it or pursued it any further, so rather than trying to retrace my steps, I started again from scratch (I also wanted to get it working on my Mac rather than on Windows).

The First Attempt – Compiling in Eclipse C++ on the Mac

Skipping a few steps to get to the more interesting details, assuming Eclipse for C++ is already downloaded and installed along with the GNU toolchain for ARM, here’s what I got building my project for the first time:

 11:54:51 **** Build of configuration arm cross compile for project ASMCrossCompile ****
 make all
 Building file: ../test.S
 Invoking: Cross GCC Assembler
 /Applications/EclipseIDEs/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-as-o "test.o" "../test.S"
 Finished building: ../test.S
 Building target: ASMCrossCompile
 Invoking: Cross GCC Linker
 /Applications/EclipseIDEs/gcc-arm-none-eabi-4_9-2015q2/bin/arm-none-eabi-gcc-L/Applications/EclipseIDEs/gcc-arm-none-eabi-4_9-2015q2/arm-none-eabi/lib -o "ASMCrossCompile" ./test.o
 /Applications/EclipseIDEs/gcc-arm-none-eabi-4_9-2015q2/arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
 exit.c:(.text.exit+0x2c): undefined reference to `_exit'
 collect2: error: ld returned 1 exit status
 make: *** [ASMCrossCompile] Error 1

This error “undefined reference to `_exit'” is described in this SO post here:
http://stackoverflow.com/questions/19419782/exit-c-text0x18-undefined-reference-to-exit-when-using-arm-none-eabi-gcc

This issue is apparently directly related to cross compiling on a different hardware architecture, and the solution is to add the –specs=nosys.specs option to the loader config. I added this in Eclipse in project properties, C/C++ Build/Settings/Cross GCC Linker and added into the Expert Settings Command Line Pattern and this fixed this issue.

Transferring the Executable to the Pi

In Eclipse C++, in the Run Configuration settings you can select ‘New Connection’ and configure a ssh connection to your Pi. You need to also set a full path on the Pi for where the file is going to be dropped.

At this point I get this error: “Error during upload : File system input or output error”. Executing the file on the Pi itself I get a Seg Fault.

Searching around, the general suggestion seems to run ‘file’ against the executable to check that it was compiled and linked against the right architecture.

For my newly cross compile file, I get this:

pi@raspberrypi~/asm $ file ASMCrossCompile
ASMCrossCompile: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, not stripped

And for an executable running correctly on the Pi I get this:

pi@raspberrypi~/asm $ file loopNums
loopNums: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x91189f47c9216e8d281238cba56b56042bcf8e6b, not stripped

Ok, so clearly I’m close but not there yet.

From other posts like this one (some of the key screenshots in this one seem missing) and this one, it seems it far easier and more direct to use the ready to go compiler crosschain from the RaspberryPi project available from github here  (and not just a more generic toolchain for ARM processors but not specifically for the Pi and/or Raspbian). This is compiled for Linux, so following the tips in the prior two articles, this was my next attempt.

Second Attempt: Eclipse C++ plus Raspberry Pi Tools toolchain … on Ubuntu … on VirtualBox … on the Mac

Clone the Tools.git project from the above github project url.

Creating a C Project

Create a new C Project, select the defaults per this screenshot:Create Project

Next through to this dialog – point to where you cloned the Raspberry Pi Tools source:


Configure toolchain path

 

  • Set the compiler prefix to:arm-linux-gnueabihf-
  • Set the path to /rpi_tools_download_dir/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

To build the project, select Build and Build All.

Done.

You should see a Binaries entry in your Project Explorer tree view appear.

To deploy the code over to the Pi we can set up the Run Configuration selecting the Remote Application option again, use ssh and point it to your Pi.

Now I’m still getting the same generic input/output error that I was before, so I Input/Output errorssh’d over to the Pi to take a look at the new file that had appeared over there, and noticed that it wasn’t executable, so on the Remote Execution step you still need to do a chmod +x on it.

Doing a file on it though shows settings that are the same as what I had on executables compiled and linked on the Pi, so now we’re looking good:

pi@raspberrypi ~/asm $ file asm_test
asm_test: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x9f6ace58f6cc2d036ea113e69dc40a5f7fc5521d, not stripped

Now we’re getting somewhere!

A quick hello world calling syscall 4 to do write to the console:

.global main
 main:
 MOV R7, #4 @ Syscall 4 = write to screen
 MOV R0, #1 @ 1=stdout: move 1 to R0
 MOV R2, #13 @ length of string to R2
 LDR R1, =string
 SWI 0
 BX lr
 string:
 .asciz "hello world!\n"

Adding the chmod seems to get us an executable on the Pi side, but still get the i/o error.

However! ssh’ing over to Pi and executing the newly transferred file:

pi@raspberrypi ~/asm $ ./asm_test
hello world!

Success! I can now use Eclipse on my Mac to develop asm for the Pi! (Although having to run it on Ubuntu on VirtualBox on the Mac, but I can live with that 🙂

Implementing simple sort algorithms in ARM Assembly (part 1)

A while back I started to learn some ARM assembly on the Raspberry Pi (out of curiosity, for no other better reason). I thought it would be interesting to couple this with re-learning some of the basic/standard/common algorithm at the same time, such as common sort algorithms.

So as my first step, since this is turning out to be far more work than I expected (!), here’s my ARM ASM source so far to iterate through a list of 4 byte integer values and print the values to the console using C’s printf. I’ll post further updates as I make progress:

[code]
.global main
main:
push {ip, lr}
MOV R6, #0 @offset to data
loop:
LDR R0, =output @load addr of output string
LDR R5, =nums @ addr of string to R5
LDR R4,[R5,R6] @load current num from R5 with offset R6
MOV R1,R4 @move num for output
BL printf
CMP R6,#16 @ 0 plus 4*4bytes for 5 entries in array
ADD R6,R6, #4 @inc offset by 4 bytes
BNE loop
_exit:
POP {ip, lr}
MOV R1, #0
MOV R7, #1
SWI 0
nums:
.word 5,2,7,1,8
.data
output:
.asciz "%d\n"
[/code]

I’m sure there’s better ways I can approach this limited code so far, but I’ll come back and revisit this again later. If anyone wants to pull or browse the source so far (and other snippets), it’s on github here: https://github.com/kevinhooke/learning-arm-asm

Configuring rtl_fm and Direwolf for decoding Amateur Radio Packet on the Raspberry Pi

rtl_fm is one of the utilities from the rtl_sdr package for using a TV dongle as an SDR. Head over here if you need more info on this.

Direwolf is a soundcard based packet modem.

According to the Direwolf docs, it supports using rtl_fm as an input, so I thought I would take a look at look at getting these running together.

I’ve used rtl_sdr and rtl_tcp on my Pi before, but not rtl_fm, so first to get this working.

To playback the stream from rtl_fm you need to pipe into into some audio app. This is the same way that direwolf is going to read the stream too. Following the suggestion here on the rtl_sdr page, this command works fine for a local broadcast radio station on 96.9MHz:

rtl_fm -f 96.9M -M wbfm -s 200000 -r 48000 | play -r 48000 -t s16 -L -c 1  -

I’m not sure what all these options are, but the key options seem to be -s for the sample rate, and -r for the resolution. The -r value needs to match on the rtl_fm side and on the play side.

Now to get direwolf installed on Raspbian:

– per the userguide, first install libasound-dev:

[code]sudo apt-get install libasound-dev[/code]

– download the source zip from: https://home.comcast.net/~wb2osz/site/?/page/Download/

– unzip and cd into the direwolf folder

– make with:

[code]make -f Makefile.linux

make install-conf

make install_rpi[/code]

At this point I have rtl_fm on the Pi working as it should, and direwolf working great when decoding audio input from a 2m radio input via a USB soundcard. Combining the two though is giving me issues.

I don’t thing I’m able to get a strong enough received signal on 2m on the RTL stick even with an external 1/4wave 2m antenna.

This is the combination of commands, rtl_fm, piping into Direwolf:


[code]rtl_fm -f 145048467 -M fm -s 200000 -r 32000 -g 35 | direwolf -n 1 -r 32000 -b 16 -t 0 -[/code]

I’ve allowed for the tuning offset ppm on this RTL card, but maybe I’ve calculated this wrong?

Anyway, since Direwolf by itself on the Pi is working well and what I needed for a small packet project was to be able to decode packet on the Pi, I’ll be putting rtl_fm on hold for the time being and playing with Direwolf by itself.

Changing display resolution on Rasbian

Settings such as HDMI video output are configured in the /boot/config.txt file – you can edit this on the Pi with ‘sudo nano /boot/config.txt’. If you need to edit on another machine, see details here.

This page lists available video modes. On my LG E2341 connected by HDMI, uncommenting and changing these two settings works to set the output to 1080p:

hdmi_group=1

hdmi_mode=16