Jump to content

    

Функция sprintf

Добрый день.

Работаю на NXP MK66FN2M0xxx18.

При этом при использовании функции sprintf для вывода чисел с плавающей запятой, программа на этой функции вылетает. Убираешь %f (т.е. выводишь все кроме float'ов) - все работает.

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

 

На сайте IAR нашел следующее https://www.iar.com/support/tech-notes/gene...point-f-on-arm/

Правда думается, что не о том.

Share this post


Link to post
Share on other sites
При этом при использовании функции sprintf для вывода чисел с плавающей запятой, программа на этой функции вылетает. Убираешь %f (т.е. выводишь все кроме float'ов) - все работает.

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

Вангую использование FPU в разных задачах РТОС (или ISR) и несохранение контекста FPU при их переключении.

Либо тупо: используется stdlib без поддержки float.

Share this post


Link to post
Share on other sites
Вангую использование FPU в разных задачах РТОС (или ISR) и несохранение контекста FPU при их переключении.

Либо тупо: используется stdlib без поддержки float.

 

либо стек не выровнен на 8

Share this post


Link to post
Share on other sites
либо стек не выровнен на 8

У меня такое приводило просто к неправильной печати. Но то был GNU Arm Embedded...

Share this post


Link to post
Share on other sites

1. Операционок нет, для прерываний контекст сохраняется и восстанавливается автоматически.

 

2. "Стэк не выровнен на 8." - поясните плз что это значит? Стэк должен начинаться с адреса кратного восьми? или все элементы в стэке должны размещаться в нем с "шагом" кратном 8? Или еще как-то?

Share this post


Link to post
Share on other sites
Стэк должен начинаться с адреса кратного восьми?

Именно. Вернее, указатель стека при вызове внешних функций должен быть кратен 8, но если стек выравнен в начале, то в дальнейшем компилятор соблюдает эту кратность. Если нарушить, бывают чудеса в частности вокруг sprintf. Должно быть, как-то замешаны вычисления с double.

Кстати, насчёт double. Если при инициализации программы не включен FPU, то при попытке его использования будет именно "улетать".

Share this post


Link to post
Share on other sites
Кстати, насчёт double. Если при инициализации программы не включен FPU, то при попытке его использования будет именно "улетать".

Вообще - ТС даже не раскрыл значение понятия "вылетает". Может если он определится - что это такое, то всё сразу станет ясно?

Share this post


Link to post
Share on other sites

Может банальное переполнение буфера?

HINT: Попробуйте на snprintf заменить и в будущем только её и использовать...

Share this post


Link to post
Share on other sites
Может банальное переполнение буфера?

HINT: Попробуйте на snprintf заменить и в будущем только её и использовать...

Кстати, да. Банальнейший код может привести к неожиданным результатам:

char buf[16];
sprintf(buf, "%f", 1.0e99); // boom

Share this post


Link to post
Share on other sites
Именно. Вернее, указатель стека при вызове внешних функций должен быть кратен 8, но если стек выравнен в начале, то в дальнейшем компилятор соблюдает эту кратность. Если нарушить, бывают чудеса в частности вокруг sprintf. Должно быть, как-то замешаны вычисления с double.

Кстати, насчёт double. Если при инициализации программы не включен FPU, то при попытке его использования будет именно "улетать".

Стек начинается с адреса кратного 8. При заходе в подпрограмму функции sprintf в регистре адреса число (почему-то) не кратное 8. Почему - фиг его знает. Переменная, в которую я запихиваю строчку при помощи функции sprintf - локальная, т.е. объявлена в той же функции, в которой я вызываю sprintf. Пока пришел к следующему: если переменную объявить глобально, то все работает. Однако объяснения этому всему пока нет.

 

Уважаемые форумчане, есть мысли на этот счет?

Share this post


Link to post
Share on other sites
Уважаемые форумчане, есть мысли на этот счет?

Уже вроде писали: телепаты в отпуске. А пока не объясните значение понятия "вылетает" помочь Вам смогут только они.

Share this post


Link to post
Share on other sites

уверен там хардварный FPU. включите его

#define CORTEX_M4_BLOCK  0xe000e000
#define CPACR *(unsigned long *)(CORTEX_M4_BLOCK + 0xd88)  // Co-processor Access Control 

//__enable_FPU();  
CPACR |= (0xf << 20);   // enable access to FPU

а вообще sprintf монструозная функция для эмбедед. никогда не использовал ее.

 

Share this post


Link to post
Share on other sites
а вообще sprintf монструозная функция для эмбедед. никогда не использовал ее.
Как же тогда делать?

 

Давно просили - про "Программа вылетает":

не знаю как это может помочь

Hard fault

HFSR 0E80

Edited by aBoomest

Share this post


Link to post
Share on other sites
Как же тогда делать?

 

Давно просили - про "Программа вылетает":

не знаю как это может помочь

Hard fault

HFSR 0E80

Вы уверены что правильно считали HFSR? :wacko:

 

а вообще sprintf монструозная функция для эмбедед. никогда не использовал ее.

Ну и зря. Не такая она и монструозная.

Edited by Arlleex

Share this post


Link to post
Share on other sites
Как же тогда делать?

 

Давно просили - про "Программа вылетает":

не знаю как это может помочь

Hard fault

HFSR 0E80

 

Посмотрите в дизассемблере содержимое функций isnanf и isinff (isinfd isnand). Скорее всего они пустые (с мусором).

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now