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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
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
AHTOXA
сообщение Feb 7 2011, 07:34
Сообщение #2


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

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



Цитата(shreck @ Feb 7 2011, 11:28) *
2. В связке CortexM3 + GCC printf сначала не работал, но после выравнивания стека задач TStackItem Stack[] на границу 8 байт, функция заработала. Выравнивание при использовании IAR не помогло.

Вот что я нарыл по этому поводу: 8 byte stack alignment is a requirement of the ARM Architecture Procedure Call Standard [AAPCS].


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


Местный
***

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



Цитата(AHTOXA @ Feb 7 2011, 14:34) *

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

Вопрос снят.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 09:05
Сообщение #4


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

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



Цитата(shreck @ Feb 7 2011, 13:25) *
Вопрос снят.

А как это выглядит в IAR-е? (Как задаётся выравнивание?)


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


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

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



Цитата(shreck @ Feb 7 2011, 11:25) *
Да, проблема именно в выравнивании стека задачи.
Сейчас на свежую голову выполнил выравнивание и все заработало.

Хм, у меня тоже проект в ИАРе.
Никакого выравнивания не делал, всё работает.
Правда, printf() не пользуюсь, только vsnprintf().

А сама операционка разве не делает выравнивание стеков задач?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 09:40
Сообщение #6


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

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



Цитата(sonycman @ Feb 7 2011, 14:34) *
Никакого выравнивания не делал, всё работает.

Там как повезёт. Добавил переменную - работает, убавил - не работаетsm.gif
Цитата(sonycman @ Feb 7 2011, 14:34) *
А сама операционка разве не делает выравнивание стеков задач?

Пока не делает, починяемsm.gif
В качестве временной меры надо в OS_Kernel.h сделать так:
Код
     __attribute__ ((aligned (8))) TStackItem Stack[stack_size/sizeof(TStackItem)];

(не знаю как в IAR задаётся выравнивание)


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


Местный
***

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



Цитата(AHTOXA @ Feb 7 2011, 16:05) *
А как это выглядит в IAR-е? (Как задаётся выравнивание?)

Сейчас временно сделал так.
При определении объекта задачи:
Код
#pragma data_alignment=8
Some_task task_obj;

Но это не совсем правильно. В scmRTOS, как мне думается, выравнивание надо делать как-то вроде этого (не помню как это называется):
Код
class process : public TBaseProcess
{
    ...
private:
    union Align_buff
    {
        long long dummy;
        TStackItem Stack[stack_size/sizeof(TStackItem)];
    };
    Align_buff buff;
};


Go to the top of the page
 
+Quote Post
sonycman
сообщение Feb 7 2011, 10:36
Сообщение #8


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

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



Цитата(AHTOXA @ Feb 7 2011, 12:40) *
Там как повезёт. Добавил переменную - работает, убавил - не работаетsm.gif

Ну, тогда, наверное, мне сильно везёт, так как вывода через vsnprintf() много и самого разного.

Кстати, мне вот не особо понятно, как применительно к стеку может относится выравнивание в 8 байт?
Ведь минимальная величина изменения указателя стека - 4 байта, не 8?
Тогда получается выравнивать надо по границе слова, а не двух слов?
Go to the top of the page
 
+Quote Post
shreck
сообщение Feb 7 2011, 10:46
Сообщение #9


Местный
***

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



Цитата(sonycman @ Feb 7 2011, 18:36) *
Ну, тогда, наверное, мне сильно везёт, так как вывода через vsnprintf() много и самого разного.

Дело не в количестве вывода через printf. Вам везет, что стек выровнен как надо. Кстати какой проц. Не факт, что вам требуется выравнивание именно на 8 байт.


Цитата(sonycman @ Feb 7 2011, 18:36) *
Кстати, мне вот не особо понятно, как применительно к стеку может относится выравнивание в 8 байт?

Требование конторы ARM, ссылка уже была. И у IARa в Development Guide для ARM Cores четко прописано 8 байтное выравнивание стека.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 10:51
Сообщение #10


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

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



Цитата(shreck @ Feb 7 2011, 14:41) *
Код
#pragma data_alignment=8
Some_task task_obj;

То есть, выравнивание стека задать таким образом нельзя, только выравнивание всего объекта? Это конечно не дело.

Цитата(sonycman @ Feb 7 2011, 15:36) *
Ну, тогда, наверное, мне сильно везёт, так как вывода через vsnprintf() много и самого разного.

Или IAR у вас старый, и ещё не научился пользоваться новыми фишкамиsm.gif

Цитата(sonycman @ Feb 7 2011, 15:36) *
Кстати, мне вот не особо понятно, как применительно к стеку может относится выравнивание в 8 байт?

Мне тоже не очень понятно. Но - стандарт, что поделать. Тем более, что имеем явный пример глюков, которые можно получить, не соблюдая этот стандарт.


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


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

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



Цитата(shreck @ Feb 7 2011, 13:46) *
Дело не в количестве вывода через printf. Вам везет, что стек выровнен как надо. Кстати какой проц. Не факт, что вам требуется выравнивание именно на 8 байт.

У меня LPC1768.
В теме, по моему, ясно написано Cortex-M3.
Неужели двум чипам на одном и том же ядре требуется разное выравнивание?

У себя использую три процесса с такими стеками:
Код
typedef OS::process<OS::pr1, 500> TProc1;
typedef OS::process<OS::pr2, 800> TProc2;
typedef OS::process<OS::pr3, 500> TProc3;

Посмотрел в map файле линкера их расположение:
Код
Proc1                   0x10001ee8  0x200  Data  Gb  main.o [1]
Proc2                   0x100020e8  0x32c  Data  Gb  main.o [1]
Proc3                   0x10002414  0x200  Data  Gb  main.o [1]

Как видно, стек третьего процесса не выровнен по границе 8 байт.
Однако же именно этот низкоприоритетный поток постоянно юзает печать через vsnprintf().

Вот и не верится мне что-то, что ваша проблема на 100% связана с выравниванием.
Цитата(AHTOXA @ Feb 7 2011, 13:51) *
Или IAR у вас старый, и ещё не научился пользоваться новыми фишкамиsm.gif

EWARM v5.50.5.
Поновее, чем у автора.
Может, наоборот, старенький ИАР подглючивает? wink.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 15:38
Сообщение #12


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

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



Цитата(sonycman @ Feb 7 2011, 19:55) *
Как видно, стек третьего процесса не выровнен по границе 8 байт.
Однако же именно этот низкоприоритетный поток постоянно юзает печать через vsnprintf().

Возможно, проблема не гарантировано появляется, а лишь с какой-то вероятностью. Или стек расположен не в начале объекта TBaseProcess, и как раз наоборот, получается выровненным. Не знаю. Попробуйте ещё добавлять/убавлять переменные, чтобы выравнивание изменилось и возможно поймаете этот глюк.
Цитата
Вот и не верится мне что-то, что ваша проблема на 100% связана с выравниванием.

Если ничего не меняя, только выравнивание, удаётся решить проблему, то вероятнее всего, что проблема именно в выравнивании, не правда ли? sm.gif
Цитата
Может, наоборот, старенький ИАР подглючивает? wink.gif

Дело в том, что и на GCC та же проблема (см. первое сообщение топика, п. 2) (это как раз я проверял, с GCC).

ЗЫ. Дополню картину. В проекте вызываю тестовую функцию дважды - один раз до вызова OS:Run(), второй - после, уже из процесса.
В первом случае результат корректный, во втором - нет. Запрет прерываний во втором случае не спасает. Зато выравнивание стека процесса - устраняет глюк. Какие тут можно придумать варианты, кроме стека?


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


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

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



Цитата(AHTOXA @ Feb 7 2011, 18:38) *
Возможно, проблема не гарантировано появляется, а лишь с какой-то вероятностью. Или стек расположен не в начале объекта TBaseProcess, и как раз наоборот, получается выровненным. Не знаю.

Да, резервируется место, на 12 байт большее отведённого места под стек.
Для чего, интересно?
Цитата(AHTOXA @ Feb 7 2011, 18:38) *
ЗЫ. Дополню картину. В проекте вызываю тестовую функцию дважды - один раз до вызова OS:Run(), второй - после, уже из процесса.
В первом случае результат корректный, во втором - нет. Запрет прерываний во втором случае не спасает. Зато выравнивание стека процесса - устраняет глюк. Какие тут можно придумать варианты, кроме стека?

Было бы неплохо для наглядности продебажить на самом низком уровне и увидеть, в каком именно месте затык.

Ведь даже если вершина стека является выровненной до 8 байт, разве не может на момент вызова любой функции текущий адрес стека быть равен его вершине-4, -12 и т.д. с кратностью 4?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 7 2011, 16:47
Сообщение #14


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

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



Цитата(sonycman @ Feb 7 2011, 21:20) *
Да, резервируется место, на 12 байт большее отведённого места под стек.
Для чего, интересно?

Как это для чего? Вот же:
Код
    class TBaseProcess
    {
...
    protected:
        TStackItem* StackPointer;
        TTimeout Timeout;
        TPriority Priority;
    };

Вот они, наши 12 байт. Итого, 0x10002414 + 12 = 0x10002420 (!) Вот потому и работает printf sm.gif

Цитата
Ведь даже если вершина стека является выровненной до 8 байт, разве не может на момент вызова любой функции текущий адрес стека быть равен его вершине-4, -12 и т.д. с кратностью 4?

Нет. Компилятор обеспечивает дискретность выделения стека, равную восьми байтам. Таким образом получается, что при условии изначального выравнивания стека на границу 8 байт, оно соблюдается (сохраняется) при любом уровне вложенности вызовов.
(ИМХО конечно)


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


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

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



Цитата(AHTOXA @ Feb 7 2011, 19:47) *
Как это для чего? Вот же:

А, точно, вот они где sm.gif
Цитата
Итого, 0x10002414 + 12 = 0x10002420 (!) Вот потому и работает printf sm.gif

Э, нет, Антоха, так просто не получится - посмотри на другие два процесса - они тоже печатью занимаются sm.gif
Там выравнивание тогда будет нарушаться.
Цитата
Нет. Компилятор обеспечивает дискретность выделения стека, равную восьми байтам. Таким образом получается, что при условии изначального выравнивания стека на границу 8 байт, оно соблюдается (сохраняется) при любом уровне вложенности вызовов.
(ИМХО конечно)

Ну если компилер поддерживает выравнивание - тогда всё в порядке.
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 Текстовая версия Сейчас: 21st June 2025 - 17:21
Рейтинг@Mail.ru


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