Включение эмуляции с плавающей запятой в gcc-arm-none-eabi

Я пытаюсь понять, как включить поддержку плавающей запятой для компилятора arm-none-eabi-gcc. Версия arm-none-eabi-gccgcc version 6.3.1 20170620 (15:6.3.1+svn253039-1build1).

У меня есть Makefile со следующими параметрами компилятора и компоновщика:

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  

Но даже после компиляции с этими параметрами я не могу использовать float или double, например. код не выполняется после, если я пытаюсь преобразовать тип double в long, например.

long var_tempNumber_u32;
double var_floatNumber_f32;
var_tempNumber_u32 = (long)var_floatNumber_f32;  

Я использую пользовательский скрипт компоновщика и в соответствии с этой ссылкой сообщества NXP я добавил GROUP(libgcc.a libc.a libm.a) перед SECTIONS строка в скрипте компоновщика.

Я работаю над микроконтроллером LPC1768.

Обновление:

После некоторых выводов я обнаружил, что Cortex-M3 переходит в обработчик Hard Fault, поэтому я установил собственный обработчик Hard Fault, чтобы получить трассировку стека, и обнаружил, что моя прошивка дает сбой после возврата из функции __aeabi_d2uiz.

Содержимое регистров ARM во время Hard Fault:

r0: 0x81
r1: 0x43C0
r2: 0xC000
r3: 0x1
r12: 0x0000000000
LR: 0xBB1B
PC: 0x884A  

Выдержка из разборки:

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  

Адрес в Link Register указывает на инструкцию внутри вышеуказанной функции, которая находится после вызова библиотечной функции __aeabi_d2uiz.
Я не эксперт в ассемблере, поэтому я не могу найти основную причину этого.
Я также безуспешно пытался увеличить .stackarea размер стека прошивки моего приложения.
Пожалуйста, дайте мне знать, как найти возможное решение этой проблемы.


person Gaurav Pathak    schedule 05.02.2019    source источник
comment
Попробуйте тоже поставить -mthumb -msoft-float в настройках компоновщика. Компоновщик также должен знать, как обрабатывать значения с плавающей запятой.   -  person Turbo J    schedule 09.02.2019
comment
@TurboJ: эти параметры уже включены в CFLAGS из Makefile.   -  person Gaurav Pathak    schedule 11.02.2019
comment
Линкер будет вызываться с LDFLAGS. CFLAGS обычно игнорируются для командной строки компоновщика.   -  person Turbo J    schedule 11.02.2019
comment
@TurboJ Тем не менее, не повезло!   -  person Gaurav Pathak    schedule 11.02.2019


Ответы (1)


После отладки и небольшого поиска в Интернете я обнаружил основную причину этой проблемы.
Проблема заключается в файле сценария компоновщика, не было раздела, определенного для раскручивания стека ARM.
Поэтому я добавил следующую строку. в мой файл сценария компоновщика:

    .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

И проблема была решена.
Для рекурсивных функций требуется раскрутка стека, поскольку вызов функции библиотеки GCC для преобразования float в int является рекурсивным, требуется раскрутка стека, которой раньше не было.

person Gaurav Pathak    schedule 11.02.2019