реклама на сайте
подробности

 
 
> scmRTOS + CortexM3 + printf, некорректная работа printf
shreck
сообщение Feb 7 2011, 06:28
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328



Столкнулся с такой проблемой.
Перестает работать printf (а также sprintf, vprintf и т.д.), если запущена ОСь. Проявляется это в том, что функция неправильно вынимает из стека, переданные ей параметры и, соответственно, неправильно их выводит.
Эффект наблюдается только на CortexM3 с компилятором IAR (конкретно 5.41.2). На ARM7, BlackFin, AVR, MSP430 - не наблюдается.
В чем может быть причина этого и как с это исправить?

Факты к размышлению.
1. У Cortexa есть два стека (в отличии от других упомянутых процев). Причем тот, который привычный CSTACK используется для прерываний. Для нужд приложения используется второй стек.
2. В связке CortexM3 + GCC printf сначала не работал, но после выравнивания стека задач TStackItem Stack[] на границу 8 байт, функция заработала. Выравнивание при использовании IAR не помогло.
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3 >  
Start new topic
Ответов (15 - 29)
AHTOXA
сообщение Feb 7 2011, 17:11
Сообщение #16


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sonycman @ Feb 7 2011, 21:59) *
Э, нет, Антоха, так просто не получится - посмотри на другие два процесса - они тоже печатью занимаются sm.gif

Точно? С printf? С плавучкой (я про это не говорил, но это важно)?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Feb 7 2011, 17:17
Сообщение #17


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(AHTOXA @ Feb 7 2011, 20:11) *
Точно? С printf? С плавучкой (я про это не говорил, но это важно)?

Да, с vsnprintf(), без плавучки.

Считаешь, что именно плавучка вызывает сбой?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 17:28
Сообщение #18


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Да, плавучка. Я не помню, где я про это читал, помню только, что именно плавучка особенно требовательна к выравниванию стека.
Собственно, благодаря этому смутному воспоминанию мы и нашли решениеsm.gif
ЗЫ. Попробуй, это ж несложноsm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
shreck
сообщение Feb 8 2011, 03:15
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328



Цитата(sonycman @ Feb 8 2011, 00:17) *
Считаешь, что именно плавучка вызывает сбой?

Да, плавучка ибо double, который как раз-таки размером 8 байт (а возможно и long long).
Go to the top of the page
 
+Quote Post
VslavX
сообщение Jan 30 2012, 00:01
Сообщение #20


embarrassed systems engineer
*****

Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038



Я тоже наступил на эти шикарные грабли. biggrin.gif
Недавно добавил в свой printf поддержку 64-битных целых (signed/unsigned long long которые). Проверил, отладил - все работает. И даже пару месяцев нормально поработало. А потом - хрясь, и все, мусор вместо 64-битных лезть начал. И не сразу докопался я, что va_arg(list, long long) неверно из стека 64-битные вынимает. Добавил выравнивание стека в порт RTOS (TNKernel, не SCM, но это неважно) при инициализации задачи - и все снова работает. Да, грабли просто шикарные, и бьют больно.
Go to the top of the page
 
+Quote Post
cerebral
сообщение Feb 21 2012, 06:53
Сообщение #21


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 8-01-09
Из: 52
Пользователь №: 43 040



Принимаю эстафету в беге по граблям.

Не могу найти причину hardfault'а в ScmRTOS после вызова sprintf. В hardfault падает из ContextRestore, на инструкции bx lr c 0xfffffffd в lr.

ScmRTOS 3.10, arm-kgp-eabi-x86_32-20111129 (с yagarto аналогично).

Оч. расчитываю на вашу помощь.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2012, 07:00
Сообщение #22


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (cerebral @ Feb 21 2012, 08:53) *
В hardfault падает из ContextRestore, на инструкции bx lr c 0xfffffffd в lr.
По симптомам очень похоже на порчу сохраненного на стеке контекста процесса. Хватает ли стека тому процессу, который вызывает sprintf? Хватает ли буфера, в который пишет sprintf?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
cerebral
сообщение Feb 21 2012, 07:30
Сообщение #23


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 8-01-09
Из: 52
Пользователь №: 43 040



Сергей, спасибо. Проблема действительно была заключена в недостаточном объёме памяти, выделенной под стек.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jan 11 2013, 12:32
Сообщение #24


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



РРРР!) Прошу прощения за поднятие старой темы... Может быть какой-нить дефайн добавим в OS_Kernel.h? Чтобы при компиляции оси под армы (под ARM7TDMI точно) стек задач выравнивался на 8. А то я уж чуть не поседел, когда несколько дней думал, почему vsprintf не печатает плавучку... Выравнивание на 8 рулит!!!

З.Ы. У меня 4-я версия, там еще ничего не выравнивается(


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 11 2013, 13:18
Сообщение #25


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(haker_fox @ Jan 11 2013, 18:32) *
З.Ы. У меня 4-я версия, там еще ничего не выравнивается(

Как это не выравнивается? Может быть, вы имели в виду 3-ю версию? Так и там исправлено (по крайней мере в 3.11/GCC - точно).
Вот же (tags/3.11/CortexM3/GCC/scmRTOS/CortexM3/OS_Target_cpp.cpp):
TBaseProcess::TBaseProcess(TStackItem* Stack, TPriority pr, void (*exec)())
: StackPointer((TStackItem*)((unsigned int)Stack & 0xFFFFFFF8))

Если у вас IAR, то поправьте по аналогии.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jan 11 2013, 13:27
Сообщение #26


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



Я имел в виду под ARM7TDMI... Принтф у меня не работала, пока я не закомментировал то, что было, и не добавил то, что ниже комментария... Версия 4.00
CODE
        class process : public TBaseProcess
        {
        public:
            INLINE_PROCESS_CTOR process();

            OS_PROCESS static void exec();
            
        #if scmRTOS_PROCESS_RESTART_ENABLE == 1
            INLINE void terminate();
        #endif
            

        private:
            //stack_item_t Stack[stack_size/sizeof(stack_item_t)];
            __attribute__ ((aligned (8))) stack_item_t Stack[stack_size/sizeof(stack_item_t)];


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 11 2013, 15:00
Сообщение #27


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(haker_fox @ Jan 11 2013, 19:27) *
Я имел в виду под ARM7TDMI...

А тема про CortexM3 sm.gif
Тут такое дело. Дефайн не поможет в общем случае. Потому что выравнивать нужно не начальную вершину стека, а его вершину после сохранения начального контекста. У ARM7 и у Cortex-M3 контекст 16 слов, поэтому можно выравнивать и так и так. А вот с Cortex-M4F такой фокус уже не прокатит, там 17 слов. Поэтому выравнивать надо не централизованно, а в порте. Лучше - так, как я сделал в порте для Cortex-M4F.
Цитата(haker_fox @ Jan 11 2013, 19:27) *
Принтф у меня не работала, пока я не закомментировал то, что было, и не добавил то, что ниже комментария...

Не, так точно не надо. Надо как-то вот так (в OS_Target_cpp.cpp):
Код
void TBaseProcess::init_stack_frame( stack_item_t * Stack
                                   , void (*exec)()
                                #if scmRTOS_DEBUG_ENABLE == 1
                                   , stack_item_t * StackBegin
                                #endif
                                   )
{
    StackPointer = (stack_item_t*)((uintptr_t)Stack & 0xFFFFFFF8);
    *(--StackPointer) = (stack_item_t)exec;    // return from interrupt address
    StackPointer -= 14;                        // emulate "push R0-R12", "push LR"
    if((uintptr_t)exec & (1 << 0))      // if exec is THUMB-mode code
        *(--StackPointer) =   0x003F;          // SR value: system mode, FIQ & IRQ enabled, THUMB mode
    else
        *(--StackPointer) =   0x001F;          // SR value: system mode, FIQ & IRQ enabled, ARM mode

#if scmRTOS_DEBUG_ENABLE == 1
...

Попробуйте, и, если всё нормально, то я внесу правку в репозиторий.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jan 11 2013, 15:29
Сообщение #28


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (AHTOXA @ Jan 12 2013, 00:00) *
А тема про CortexM3 sm.gif
Попробуйте, и, если всё нормально, то я внесу правку в репозиторий.

Про кортекс не заметил, был увлечен ARM7 rolleyes.gif

Поправки внес. Все запустилось и работает прекрасно. Надеюсь, что если пошло, то вылетов на этой почве уже не будет.

Спасибо! rolleyes.gif


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 11 2013, 16:54
Сообщение #29


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Исправил в репозитории.

Попутно вскрылся интересный факт - я правил с старом репозитории, а в новом изменения пока не появились. Выходит, это два разных репозитория, и они синхронизируются. Надо тогда поаккуратнее быть...


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jan 15 2013, 14:10
Сообщение #30


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (AHTOXA @ Jan 12 2013, 01:54) *
Исправил

Что-то не так... Сейчас снова одни нули вместо плавучки выводятся. Причем если вернуть определение стека так, как я первоначально сделал - то работает. Как Вы предложили - нет crying.gif Неужели я в прошлый раз как-то компильнул проект не так maniac.gif Оперативы у меня 32 метра, дефицита не наблюдается. malloc() столь необходимая (иногда?) printf - работает.

Пока думаю, куда копать...

Для очистки совести сделал
CODE
make clean && make all

для двух вариантов...

Вывод 1 (плохой)
CODE
#ai6di2
ADC0: 0x81 129 0.00
ADC1: 0x80 128 0.00
ADC2: 0x80 128 0.00
ADC3: 0x80 128 0.00
ADC4: 0x7f 127 0.00
ADC5: 0x7b 123 0.00


Вывод 2 (хороший)
CODE
#ai6di2
ADC0: 0x81 129 2.52
ADC1: 0x80 128 2.50
ADC2: 0x80 128 2.50
ADC3: 0x80 128 2.50
ADC4: 0x7f 127 2.48
ADC5: 0x7b 123 2.40


Сама функция работает (текст, hex, dec)

AHTOXA, а почему не стоит делать правку в кернел.h? Ведь это логично, там мы выравниваем стек именно процессов? Более того, Вы сами предложили этот вариант в первых постах) Нэ понимает моя)))

З.Ы. Блин, в map-файле от GCC без поллитра не разберешься...

Пошел мой разбор полетов:
1. По-сути при создании процесса мы попадаем в функцию
CODE
init_stack_frame
, которая инициализиует стэк. И уже там "готовится" указатель, выровненный пока не понятным для меня ( к сожалению опыта мало) образом. Т.е. что там, что тут - вроде без разницы...


--------------------
Выбор.
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 20:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01514 секунд с 7
ELECTRONIX ©2004-2016