Question

I'm trying to build the foreign function interface library for a Cortex-M3 processor using GCC. According to http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html:

-mthumb
Generate code for the Thumb instruction set. The default is to use the 32-bit ARM instruction set. This option automatically enables either 16-bit Thumb-1 or mixed 16/32-bit Thumb-2 instructions based on the -mcpu=name and -march=name options. This option is not passed to the assembler. If you want to force assembler files to be interpreted as Thumb code, either add a `.thumb' directive to the source or pass the -mthumb option directly to the assembler by prefixing it with -Wa.

I've tried passing various various arguments to the assembler and can't seem to figure it out. Typical output as follows:

Building file: ../source/ffi/sysv.S
Invoking: GCC Assembler
arm-bare_newlib_cortex_m3_nommu-eabi-gcc -Wa,-mthumb-interwork -I"/home/neil/m3projects/robovero/firmware/include" -o"source/ffi/sysv.o" "../source/ffi/sysv.S"
../source/ffi/sysv.S: Assembler messages:
../source/ffi/sysv.S:145: Error: selected processor does not support ARM opcodes
../source/ffi/sysv.S:147: Error: attempt to use an ARM instruction on a Thumb-only processor -- `stmfd sp!,{r0-r3,fp,lr}'
...

Can I use libffi on Cortex-M3 without becoming an assembly expert?

It might be worth noting that when I invoke arm-bare_newlib_cortex_m3_nommu-eabi-as directly I get different errors.

Was it helpful?

Solution

I hate to say it but it is a porting effort. Doable, not necessarily having to be an assembler expert, but will need to learn some. Going from thumb to arm is easy, thumb2, I would have to look that up, much of thumb2 is just thumb instructions. and thumb has a one to one mapping to arm instructions, but not the other way around. Thumb mostly limits you to the lower 8 registers on all the workhorse instructions, with special versions or special instructions to use the upper registers. So many of your arm instructions are going to turn into more than one thumb instruction.

Initially see if there is a build option to build this package without using assembler or go into that directory and see if there is something you can do in the makefile to use a C program instead of assembler. I assume there is a serious performance issue to using C which is why there is assembler to start with. Thumb2 in theory is more efficient than arm but that does not necessarily mean a direct port from arm to thumb2. So with some experience you may be able to hand port to thumb2 and keep some performance.

EDIT:

Downloaded the file in question. The define stuff up front implies that it is aware of both thumb and armv7m. is that how you are getting to where you were changing stm to push?

OTHER TIPS

I modify the sysV.S as follolwing, the error is caused by the ".arm" directive, when using cortex-m3, it should be comment out.

#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
#undef __THUMB_INTERWORK__
#endif

#if __ARM_ARCH__ >= 5
# define call_reg(x)    blx x
#elif defined (__ARM_ARCH_4T__)
# define call_reg(x)    mov lr, pc ; bx x
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
#  define __INTERWORKING__
# endif
#else
# define call_reg(x)    mov lr, pc ; mov    pc, x
#endif

/* Conditionally compile unwinder directives.  */
#ifdef __ARM_EABI__
#define UNWIND
#else
#define UNWIND @
#endif  


#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
.macro  ARM_FUNC_START name
    .text
    .align 0
    .thumb
    .thumb_func
#ifdef __APPLE__
    ENTRY($0)
#else
    ENTRY(\name)
#endif
#ifndef __ARM_ARCH_7M__ /* not cortex-m3 */
    bx  pc
    nop
    .arm
#endif
    UNWIND .fnstart
/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
   directly from other local arm routines.  */
#ifdef __APPLE__
_L__$0:
#else
_L__\name:
#endif
.endm

The assembler is telling you the truth - ARM assembly code can't be assembled to work successfully on a Thumb-2-only processor like the M3. There are no way for the assembler to map the ARM instruction mnemonics into opcodes that will make sense to a Cortex-M3. You'll need to port the assembly files to Thumb-2 assembly code to get things working. Depending on what the original assembly code does, you might get lucky and be able to port to C instead, but that may cost you a major performance hit.

Add "-Wa,-mimplicit-it=thumb" to the gcc CFLAGS to avoid "thumb conditional instruction should be in IT block" error

--- libffi.orig/src/arm/sysv.S
+++ libffi/src/arm/sysv.S
@@ -91,6 +91,10 @@
 # define __ARM_ARCH__ 7
 #endif

+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+#undef __THUMB_INTERWORK__
+#endif
+
 #if __ARM_ARCH__ >= 5
 # define call_reg(x)   blx x
 #elif defined (__ARM_ARCH_4T__)
@@ -121,9 +125,11 @@
 #else
    ENTRY(\name)
 #endif
+#ifndef __ARM_ARCH_7M__ /* not cortex-m3 */
    bx  pc
    nop
    .arm
+#endif
    UNWIND .fnstart
 /* A hook to tell gdb that we've switched to ARM mode.  Also used to call
    directly from other local arm routines.  */
@@ -164,6 +170,10 @@ _L__\name:
 #endif
 .endm

+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   .syntax unified
+#endif
+
    @ r0:   ffi_prep_args
    @ r1:   &ecif
    @ r2:   cif->bytes
@@ -180,7 +190,11 @@ ARM_FUNC_START ffi_call_SYSV
    UNWIND .setfp   fp, sp

    @ Make room for all of the new args.
+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   sub sp, sp, r2
+#else
    sub sp, fp, r2
+#endif

    @ Place all of the ffi_prep_args in position
    mov r0, sp
@@ -193,7 +207,12 @@ ARM_FUNC_START ffi_call_SYSV
    ldmia   sp, {r0-r3}

    @ and adjust stack
+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   mov lr, sp
+   sub lr, fp, lr  @ cif->bytes == fp - sp
+#else
    sub lr, fp, sp  @ cif->bytes == fp - sp
+#endif
    ldr ip, [fp]    @ load fn() in advance
    cmp lr, #16
    movhs   lr, #16
@@ -305,7 +324,13 @@ ARM_FUNC_START ffi_closure_SYSV
    beq .Lretlonglong
 .Lclosure_epilogue:
    add sp, sp, #16
+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   ldr     ip, [sp, #4]
+   ldr     sp, [sp]
+   mov     pc, ip
+#else
    ldmfd   sp, {sp, pc}
+#endif
 .Lretint:
    ldr r0, [sp]
    b   .Lclosure_epilogue
@@ -381,7 +406,12 @@ LSYM(Lbase_args):
    ldmia   sp, {r0-r3}

    @ and adjust stack
+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   mov lr, sp
+   sub lr, ip, lr  @ cif->bytes == (fp - 64) - sp
+#else
    sub lr, ip, sp  @ cif->bytes == (fp - 64) - sp
+#endif
    ldr ip, [fp]    @ load fn() in advance
         cmp    lr, #16
    movhs   lr, #16
@@ -469,7 +499,13 @@ ARM_FUNC_START ffi_closure_VFP

 .Lclosure_epilogue_vfp:
    add sp, sp, #72
+#ifdef __ARM_ARCH_7M__ /* cortex-m3 */
+   ldr     ip, [sp, #4]
+   ldr     sp, [sp]
+   mov     pc, ip
+#else
    ldmfd   sp, {sp, pc}
+#endif

 .Lretfloat_vfp:
    flds    s0, [sp]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top