Перейти к содержанию
    

Вывод float в arm-none-eabi-gcc для stmf4

Добрый день.

 

Я меня возникли некоторые проблемы с выводом в терминал значений с плавающей точкой. Самый обычный sprintf прекрасно работает с целыми числами и отказывается работать с float. Например

 

   float flttest = 123.45678;

   sprintf(TestArray, "-= %lf =-", flttest);
   Terminal("Test1: STR %s", TestArray);

   uint16_t integer= 12345;
   sprintf(TestArray, "*- %d -*", integer);
   Terminal("Test2: STR %s", TestArray);

 

При этот вывод:

003 INFO: Test1: STR -= 403099659660755.687500 =-

004 INFO: Test2: STR *- 12345 -*

 

Основные ключи компилятора: arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mlittle-endian -mthumb-interwork -ffunction-sections -fdata-sections -Wl,--gc-sections

Основные ключи линкера: arm-none-eabi-gcc -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Xlinker -Map="project.map" -L/opt/gcc-arm-none-eabi-5_4/arm-none-eabi/lib/armv7e-m/fpu/ --specs=rdimon.specs -T/Core/STM32F4XX_FLASH.ld

 

Кто-либо сталкивался с подобным?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В командную строку линкера нужно добавить "-u _printf_float". Первоисточник.

 

На самом деле пробовал с -u _printf_float и с -u _sprintf_float с одинаковым результатом.

Изменено пользователем zemlemer

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я невнимательно посмотрел. Если линкуется целочисленная версия, не будет вот этих странных чисел.

Обратите внимание на выравнивание стека по границе 8 байт. Помню, это приводило к чудесам в плавучке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё вариант: https://github.com/emb-lib/io

 

библиотека, оптимизированная для embedded применений. Плавучку печатает без нареканий (только нужно определить макро PRINTF_FLOAT, лучше всего передать в командной строке -DPRINTF_FLOAT).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я невнимательно посмотрел. Если линкуется целочисленная версия, не будет вот этих странных чисел.

Обратите внимание на выравнивание стека по границе 8 байт. Помню, это приводило к чудесам в плавучке.

 

Вроде к линковщике секция с правильным ALIGN, или я не правильно понял.

  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    PROVIDE ( __end__ = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM

Вообще ситуация еще более печальна. Задавая вопрос, я просто упростил сложившуюся ситуацию. На самом деле я пишу небольшую библиотеку для отладочного вывода. Парсер разбора форматной строки - va_arg - корректно работает с целочисленными переменными. Т.е. intarg = va_arg(ap, int32_t); отрабатывает корректно. Как только речи идет о передаче плавучки - doublearg = va_arg(ap, double); - передается мусор. Если передать float через *((int32_t*)&floatarg и передать через va_arg(ap, int32_t); - передается правильно.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

float flttest = 123.45678;

 

sprintf(TestArray, "-= %lf =-", flttest);

если у вас одинарная точность, sprintf хочет %f или %e или %g, а если двойная, то да, с "l" надо писать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если у вас одинарная точность, sprintf хочет %f или %e или %g, а если двойная, то да, с "l" надо писать.

У sprintf не бывает одинарной точности, "l" игнорируется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если у вас одинарная точность, sprintf хочет %f или %e или %g, а если двойная, то да, с "l" надо писать.

Знаю. Просто va_arg не работает с float, поэтому перед передачей я преобразовывал в double а после - обратно во float.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде к линковщике секция с правильным ALIGN, или я не правильно понял.

._user_heap_stack :

{

. = ALIGN(4);

Ещё раз: выравнивать по границе 8 байт. Проверяйте на входе в sprintf(). Внутрисхемным отладчиком остановите на входе в функцию и посмотрите на SP. Если не кратно 8 - беда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

перед передачей я преобразовывал в double а после - обратно во float.

про "после" подробнее... желательно с кодом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У sprintf не бывает одинарной точности, "l" игнорируется.
Я каждый раз задаюсь вопросом: в чём был смысл такого решения при создании сишной библиотеки?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я каждый раз задаюсь вопросом: в чём был смысл такого решения при создании сишной библиотеки?

 

Смыслов несколько. У меня статически выделен массив для передачи строки в терминал, а стандартные работают с динамическим перераспределением памяти. Использовать malloc или realloc нужно когда совсем припрет. Мне не нужны все возможности printf или sprintf (кто-нить использовал \b или \v или ..... ), но все лишнее намертво прилепится к выходному бинарнику.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я каждый раз задаюсь вопросом: в чём был смысл такого решения при создании сишной библиотеки?

Между прочим, если функция имеет переменное число аргументов (как sprintf), аргументы типа float приводятся к типу double перед вызовом функции. Отцы-основатели не подумали о микроконтроллерах. Да их (МК) тогда и не было, наверное :laughing:

 

Мне не нужны все возможности printf или sprintf (кто-нить использовал \b или \v или ..... ), но все лишнее намертво прилепится к выходному бинарнику.

Уже проверили выравнивание стека, кратное 8 байт? Просто интересно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...