log2 вызывает ошибку в MCU STM32F4 в C - PullRequest
1 голос
/ 28 сентября 2019

Почему этот код вызывает серьезную ошибку и переходит в бесконечный цикл?

#include <stdint.h>
#include <math.h>

void myfunc()
{  
    const double val = 1;
    double log_res = log2(val); // <----- THIS CAUSES A FAULT
    //double log_res = log2(1); // This works
}

Когда я заменяю val в строке зла жестко закодированной 1, код работает.Таким образом, проблема возникает, только когда я передаю val в log2 (как показано в коде).Почему это происходит?

Я использую STM32CubeIDE (на основе Eclipse) с STM32F429ZI MCU.

ОБНОВЛЕНИЕ:

Проверка исключения в окне разборки показала, что этовозникла исключительная ситуация:

fffffff9: не удалось выполнить команду MI: -data-disassemble -s 4294967289 -e 4294967429 - 3 Сообщение об ошибке от серверной части отладчика: невозможно получить доступ к памяти по адресу 0xfffffffe

Кто-нибудь знает, почему это происходит?

Обновление 2:

Отладка в инструкциях по сборке:

54            const double val = 1;
08000e0a:   mov.w   r3, #0
08000e0e:   ldr     r4, [pc, #64]   ; (0x8000e50 <myfunc+88>)
08000e10:   strd    r3, r4, [r7, #16]
55            double log_res = log2(val);
08000e14:   vldr    d0, [r7, #16] // <------ X THIS LINE CAUSES THE PROBLEM X
08000e18:   bl      0x8002a9c <log>
08000e1c:   vmov    r0, r1, d0
08000e20:   add     r3, pc, #36     ; (adr r3, 0x8000e48 <myfunc+80>)
08000e22:   ldrd    r2, r3, [r3]
08000e26:   bl      0x800085c <__divdf3>

Выделенная строка имеет d0 =0, r7 = 0x2002ffcc

После выполнения этой строки дизассемблер переходит к WWDG_IRQHandler.

Обновление 3:

Параметры ассемблера GCC (не уверен, что это делает):

-mcpu=cortex-m4 -g3 -c -x assembler-with-cpp --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

Параметры компилятора GCC:

-mcpu=cortex-m4 -std=gnu11 -g3 -DSTM32F429I_DISC1 -DSTM32 -DSTM32F429ZITx -DSTM32F4 -DDEBUG -DSTM32F429xx -c -I..\Inc -I../Inc/CMSIS/Include -I../Inc/CMSIS/Device/ST/STM32F4xx/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

Параметры компоновщика GCC:

-mcpu=cortex-m4 -T"C:\Users\mne\STM32CubeIDE\workspace_1.0.0\MyUSB\STM32F429ZITX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${ProjName}.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group

Ответы [ 3 ]

2 голосов
/ 30 сентября 2019

Вы, похоже, опускаете флаги -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb в параметрах компилятора и включаете их только в параметры ассемблера.(Вы можете заменить -march=armv7-m -mtune=cortex-m4 на -mcpu=cortex-m4.) Следовательно, ваш компилятор генерирует код для неверного ABI с плавающей точкой.Вы указали жесткий ABI, но генерируете вызов функции мягкой библиотеки, а не встроенных инструкций по сборке.

Обратите внимание, что любой уровень оптимизации, даже -O1, достаточен для GCC, чтобы сложить константу и оптимизироватьзвонок на double position = 0.0;.Возможно, вам понадобится функция return position;, чтобы заставить ее генерировать этот код с включенной оптимизацией.(Я предполагаю, что это упрощенный MCVE, так как вам никогда не понадобится вычислять log2(1) во время выполнения.)

0 голосов
/ 30 сентября 2019

Проблема здесь:

08000e14: vldr d0, [r7, # 16] // <------ X ЭТА ЛИНИЯ ВЫЗЫВАЕТ ПРОБЛЕМУ X </p>

"d0" - это 64-битный регистр VFP.Однако Cortex-M4F имеет только 32-битный FPU (регистры s0, s1 и т. Д.).Cortex-M7F имеет 64-битный FPU, но это не то, что вы используете.

Так что инструкция недействительна для ядра Cortex-M4F, которое вызывает ошибку.Я могу продублировать это с выпуском GCC 2018-Q4.Проблема исчезнет, ​​если вы удалите -mfloat-abi = hard, так как он затем использует регистры ядра ARM для передачи аргумента.Так что это исправление я бы порекомендовал.

Что касается основной причины, мне нужно будет провести еще несколько расследований.

0 голосов
/ 30 сентября 2019

относительно вашего вопроса:

Когда я заменяю val в строке зла жестко закодированной 1, код работает.Так что проблема возникает только когда я передаю val в log2 (как показано в коде).Почему это происходит?

Следующее утверждение:

double position = log2(first_set);

НЕ передает переменную val в функцию: log2()

Я быожидать, что такая ошибка кодирования (поскольку first_set не определена) приведет к тому, что код не будет компилироваться.

...