gcccross-compilingcortex-mnewlib

Enabling floating point emulation in gcc-arm-none-eabi


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.


Solution

  • 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.