I am trying to figure out how should I enable soft floating point support for arm-none-eabi-gcc
compiler. The version of arm-none-eabi-gcc
is gcc version 6.3.1 20170620 (15:6.3.1+svn253039-1build1)
.
I have a Makefile with following compiler and linker options:
CFLAGS = -W -Wall -O0 --std=gnu99 -fgnu89-inline -mcpu=cortex-m3 -mthumb -msoft-float
CFLAGS += -ffunction-sections -fdata-sections -mfloat-abi=soft -u _printf_float -u _scanf_float
LDFLAGS = -nostartfiles -specs=rdimon.specs -specs=nano.specs -lc -lrdimon -u _printf_float -u _scanf_float
But even after compiling with these options I am not able to use float
or double
, for e.g. the code doesn't execute after, if I try to typecast double to long e.g.
long var_tempNumber_u32;
double var_floatNumber_f32;
var_tempNumber_u32 = (long)var_floatNumber_f32;
I am using a custom linker script and as per this NXP Community Link I have added GROUP(libgcc.a libc.a libm.a)
before SECTIONS
line in linker script.
I am working on LPC1768 micro-controller.
Update:
After some findings I found out that Cortex-M3 is going into Hard Fault handler, so I installed a custom hard-fault handler to get the stack trace and I found out that my firmware is crashing after returning from __aeabi_d2uiz
function.
Contents of ARM registers at the time of Hard Fault:
r0: 0x81
r1: 0x43C0
r2: 0xC000
r3: 0x1
r12: 0x0000000000
LR: 0xBB1B
PC: 0x884A
Excerpt from the disassembly:
0000baf0 <UART_TxFloatNumber>:
baf0: b590 push {r4, r7, lr}
baf2: b085 sub sp, #20
baf4: af00 add r7, sp, #0
baf6: e9c7 0100 strd r0, r1, [r7]
bafa: 205a movs r0, #90 ; 0x5a
bafc: f7fe fcc8 bl a490 <xMBPortSerialPutByte>
bb00: 2058 movs r0, #88 ; 0x58
bb02: f7fe fcc5 bl a490 <xMBPortSerialPutByte>
bb06: 200d movs r0, #13
bb08: f7fe fcc2 bl a490 <xMBPortSerialPutByte>
bb0c: 200a movs r0, #10
bb0e: f7fe fcbf bl a490 <xMBPortSerialPutByte>
bb12: e9d7 0100 ldrd r0, r1, [r7]
bb16: f7fc fce5 bl 84e4 <__aeabi_d2uiz>
bb1a: 4603 mov r3, r0
bb1c: 60fb str r3, [r7, #12]
bb1e: 21ff movs r1, #255 ; 0xff
bb20: 68f8 ldr r0, [r7, #12]
bb22: f7ff ff5d bl b9e0 <UART_TxDecimalNumber>
bb26: 202e movs r0, #46 ; 0x2e
bb28: f7ff febc bl b8a4 <uart3_tx_byte>
bb2c: 68f8 ldr r0, [r7, #12]
bb2e: f7fc f91f bl 7d70 <__aeabi_ui2d>
bb32: 4603 mov r3, r0
bb34: 460c mov r4, r1
bb36: 461a mov r2, r3
bb38: 4623 mov r3, r4
bb3a: e9d7 0100 ldrd r0, r1, [r7]
bb3e: f7fb ff8d bl 7a5c <__aeabi_dsub>
bb42: 4603 mov r3, r0
bb44: 460c mov r4, r1
bb46: e9c7 3400 strd r3, r4, [r7]
bb4a: a30b add r3, pc, #44 ; (adr r3, bb78 <UART_TxFloatNumber+0x88>)
bb4c: e9d3 2300 ldrd r2, r3, [r3]
bb50: e9d7 0100 ldrd r0, r1, [r7]
bb54: f7fc f98c bl 7e70 <__aeabi_dmul>
bb58: 4603 mov r3, r0
bb5a: 460c mov r4, r1
bb5c: 4618 mov r0, r3
bb5e: 4621 mov r1, r4
bb60: f7fc fcc0 bl 84e4 <__aeabi_d2uiz>
bb64: 4603 mov r3, r0
bb66: 60fb str r3, [r7, #12]
bb68: 21ff movs r1, #255 ; 0xff
bb6a: 68f8 ldr r0, [r7, #12]
bb6c: f7ff ff38 bl b9e0 <UART_TxDecimalNumber>
bb70: bf00 nop
bb72: 3714 adds r7, #20
bb74: 46bd mov sp, r7
bb76: bd90 pop {r4, r7, pc}
bb78: 00000000 andeq r0, r0, r0
bb7c: 412e8480 smlawbmi lr, r0, r4, r8
The address in Link Register is pointing to the instruction inside the above function which is after __aeabi_d2uiz
library function call.
I am not that expert in assembly so I am not able to find the root cause of it.
I also tried increasing the .stackarea
i.e. stack size of my application firmware without any luck.
Please anyone, let me know how to find a possible resolution of this issue.
After debugging and searching a bit on the internet I found out the root cause of this issue.
The issue is in the Linker Script file, there was no section defined for ARM stack unwinding.
So I added the following line into my linker script file:
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > IROM
/*
* Arm stack unwinding.
* If removed may cause random crashes.
*/
.ARM.exidx :
{
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > IROM
And the issue got resolved.
Stack unwinding is required for recursive functions, because of the GCC library function call for the float to int conversion is recursive, stack unwinding is required which was not present previously.