Can Libffi be built for Cortex-M3?
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 ar开发者_如何学Cguments 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.
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
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?
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]
精彩评论