Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как определить максимальную реальную глубину CSTACK моей программы?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Разработчики
Есть ли какая-нибудь встроенная особенность отладчика IAR, которая автоматически показывает максимальную глубину CSTACK, которая произошла в моей программе за время отладки встроенным отладчиком?

Сейчас приходится вручную приблизительно прикидывать, сколько скушает SCTACK, а хотелось бы поточнее.

Думаю, вопрос подойдет про разные платформы. Конкретно - AVR.
Непомнящий Евгений
Заполняете область стека неким шаблоном (0xff, 0xDEAD, etc) и смотрите, где шаблон нарушен - туда опускался стек
Разработчики
Цитата(Непомнящий Евгений @ Oct 14 2015, 11:44) *
Заполняете область стека неким шаблоном (0xff, 0xDEAD, etc) и смотрите, где шаблон нарушен - туда опускался стек


Да, сейчас так и делаю. Даже можно ничем не заполнять, потому что само заполняется ненулями.
Но может есть что-то встроенное.
Сергей Борщ
Можно попросить линкер построить дерево вызовов и сложить глубину основного цикла с максимальной глубиной обработчиков прерываний. Вообще без отладчика.
Разработчики
Спасибо. Я посмотрел, он довольно сильно завышает.

А можно как-то из программы определить границы (начало и конец) SCTACK - где расположено?
jcxz
Цитата(Сергей Борщ @ Oct 14 2015, 15:43) *
Можно попросить линкер построить дерево вызовов и сложить глубину основного цикла с максимальной глубиной обработчиков прерываний. Вообще без отладчика.

Не канает если есть косвенные вызовы.

Цитата(Разработчики @ Oct 14 2015, 17:21) *
А можно как-то из программы определить границы (начало и конец) SCTACK - где расположено?

Стек в программе не определяют, а задают. Если что. Так же как любой другой массив.
den_po
Цитата(Разработчики @ Oct 14 2015, 14:21) *
А можно как-то из программы определить границы (начало и конец) SCTACK - где расположено?

__segment_begin("CSTACK")
__segment_end("CSTACK")

и нужно не забыть заранее сделать так:
#pragma segment = "CSTACK"
Разработчики
Цитата(den_po @ Oct 14 2015, 15:53) *
и нужно не забыть заранее сделать так:
#pragma segment = "CSTACK"


Я имел в виду системный сегмент CSTACK, а не мой.

Цитата(jcxz @ Oct 14 2015, 15:49) *
Стек в программе не определяют, а задают. Если что. Так же как любой другой массив.


Для массива можно из программы узнать, куда его запихал компилятор. А CSTACK?
den_po
Цитата(Разработчики @ Oct 14 2015, 16:55) *
Я имел в виду системный сегмент CSTACK, а не мой.

Они оба - один и тот же сегмент. Просто сишный компилятор не знает о нём, если ему не подсказать.
Разработчики
Цитата(den_po @ Oct 14 2015, 17:01) *
Они оба - один и тот же сегмент. Просто сишный компилятор не знает о нём, если ему не подсказать.


Понял. Спасибо!
jcxz
Цитата(Разработчики @ Oct 14 2015, 19:55) *
Для массива можно из программы узнать, куда его запихал компилятор. А CSTACK?

Я не знаю, что в Вашей программе означает символьное имя CSTACK. Это только Вы можете знать. В моих проектах это имя не используется.
У меня есть массив
static __root __no_init OS_STK stkTaskMain[NNN + STK_SIZE_ISR_NFP] @ ".bssStkMain";
задающий стек используемый стартапом и функцией main() (и, впоследствии, после старта ОС, другой задачей), есть сегмент .bssStkMain, в который линкуется этот массив и указатель на конец которого записывается в вектор сброса.
Есть множество других стеков задач ОС, каждый задан массивом типа
__no_init static OS_STK stkXXX[NNN + STK_SIZE_ISR_NFP] @ ".bssStk";
И место под любой стек задаётся статическим массивом в исходниках либо в файле конфигурации компоновщика (*.icf в IAR).
den_po
Цитата(jcxz @ Oct 15 2015, 08:23) *
Я не знаю, что в Вашей программе означает символьное имя CSTACK. Это только Вы можете знать. В моих проектах это имя не используется.

То есть вы НИКОГДА не использовали иаровский стартап и его же конфиги линкера по умолчанию?
jcxz
Цитата(den_po @ Oct 15 2015, 12:38) *
То есть вы НИКОГДА не использовали иаровский стартап и его же конфиги линкера по умолчанию?

Когда-то давно использовал. Но это было давно. Последние годы использую везде (в ARM) только свои стартапы.
Target
А подскажите, как получить трехбайтовую величину? Хочу получить длину программы по окончанию сегмента NEAR_ID.
Пытаюсь получить адрес сегмента NEAR_ID.

Делаю так:

#pragma segment = "NEAR_ID"
unsigned long * pNEAR_ID_end = (unsigned long *)__segment_end("NEAR_ID");


Компилятор ругается так:

Linking
Warning[w47]: Range error,
Number out of range. Valid range is -128 (-0x80) to 255 (0xFF).
File: main.cpp, Line: 247
Source: LDI R17, (SFE(NEAR_ID)) >> 8

Если вместо unsigned long ставить void или word, то выдает только 2 байта, а третий - ноль.
SSerge
Цитата(Target @ Nov 25 2015, 18:33) *
А подскажите, как получить трехбайтовую величину? Хочу получить длину программы по окончанию сегмента NEAR_ID.
Пытаюсь получить адрес сегмента NEAR_ID.

Очень похоже на то, что сказывается гарвардская архитектура AVR. Указатели на память данных и память кода это две совершенно разные сущности и просто так не смешиваются.
А у Вас как раз написано unsigned long * pNEAR_ID_end = ..., что подразумевает указатель на память данных, в то время как сегмент NEAR_ID располагается во флеше.
В EWAVR_CompilerReference.pdf есть подсказка:
Цитата
If the segment was declared with a memory attribute
memattr, the type of the __segment_begin operator is a pointer to memattr void.
Otherwise, the type is a default pointer to void.

Попробуйте так:
#pragma segment = "NEAR_ID" __farflash
char __farflash* pNEAR_ID_end = __segment_end("NEAR_ID");
а то и просто
uint32_t pNEAR_ID_end = __segment_end("NEAR_ID");
Ga_ry
Что то читал, читал эту ветку и так и не понял как определить хватает места программе для стека или нет.
Вот например (IAR AVR) изначально по умолчанию 0x20 явно не хватало, шли сбои, увеличил до 0x44
вот последние строчки из MAP
Цитата
CSTACK DATA 00000100 - 00000144 45 dse 0
RSTACK DATA 00000145 - 00000178 34 dse 0
NEAR_I DATA 00000179 - 00000284 10C rel 0
NEAR_Z DATA 00000285 - 000002DF

во вложении скриншот memory data после работы программы

Как понять сейчас хватает программе этого размера?
Какой минимум можно оставить для CSTACK?

kolobok0
Цитата(Ga_ry @ Nov 25 2015, 22:15) *
...Как понять сейчас хватает программе этого размера?Какой минимум можно оставить для CSTACK?..


делаете три вещи
1) при выделении стэка расписываете магическим числом всю память под стэк.
2) в определённые срезы времени проверяете сколько памяти осталось расписанной вашим магическим числом(например при переключении задач, если ось)
3) скидываете каждые изменения размеров остатков стэков в лог

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

Ga_ry
Понятно.
Вот только логи мне писать некуда, 8к почти под завязку (20 байт осталось) т.е. код для формир. лога вставить тоже некуда. Ноги МК тоже, НИ ОДНОЙ свободной.
Брать контроллер с большей памятью, отладку делать на нем?

А вот это изначальное заполнение FF не пойдет для магического числа?
Target
Цитата(SSerge @ Nov 25 2015, 15:51) *
#pragma segment = "NEAR_ID" __farflash
char __farflash* pNEAR_ID_end = __segment_end("NEAR_ID");


Спасибо!

Помогло так:

#pragma segment = "NEAR_ID" __farflash
void __farflash * pNEAR_ID_end = __segment_end("NEAR_ID");


Цитата(Ga_ry @ Nov 26 2015, 00:09) *
А вот это изначальное заполнение FF не пойдет для магического числа?


Обычно там 00. Можно в прерывании по таймеру или кнопке искать адрес первого ненулевого байта.
Ga_ry
Цитата(Target @ Nov 26 2015, 10:20) *
Обычно там 00.

Странно, в скриншоте, который прикреплен, видно FF
kolobok0
Цитата(Ga_ry @ Nov 26 2015, 00:09) *
...изначальное заполнение FF не пойдет для магического числа?


20 байт - можно использовать для многого sm.gif под отладчиком для просмотра/контроля - вполне.
а вот FF - тут дело такое. для скорости проверки необходимо брать всю разрядность шины данных. т.е. если у вас используются 32 разрядный мк -
то это уже 4 байта за раз можно писать/тестировать/сравнивать...

нолик 0x00 как и минус один(в стандарте сей) 0xFF чаще встречается чем какие-либо другие комбинации.
Ga_ry
kolobok0, а зачем надо умножать на два?
x893
а разве DEADBEEF не помогает - или религия запрещает ?
проблема из пальца выдуманная
kolobok0
Цитата(Ga_ry @ Nov 27 2015, 00:21) *
kolobok0, а зачем надо умножать на два?


тут именно посыл вектора поиска от большего к меньшему. т.е. не искать где нехватка, а искать где слишком много и не юзается...
Ga_ry
Цитата(x893 @ Nov 27 2015, 00:04) *
а разве DEADBEEF не помогает - или религия запрещает ?
проблема из пальца выдуманная

Этот Ваш стиль надменно-пренебрежительный это врожденное или приобретенное?
Ссылку дайте, я первый раз слышу о таком.
k155la3
Цитата(kolobok0 @ Nov 26 2015, 00:49) *
делаете три вещи
1) при выделении стэка расписываете магическим числом всю память под стэк.
2) в определённые срезы времени проверяете сколько памяти осталось расписанной вашим магическим числом(например при переключении задач, если ось)
3) скидываете каждые изменения размеров остатков стэков в лог

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


В ОС (из-за многостековости) имеются "включаемые" режимы контроля размера стек(ов).
Алгоритм тот что указан выше.

freeRTOS:
Код
#if( configCHECK_FOR_STACK_OVERFLOW == 1 )

    /* FreeRTOSConfig.h is only set to use the first method of
    overflow checking. */
    #define taskSECOND_CHECK_FOR_STACK_OVERFLOW()

#endif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.