Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Расчёт глубины стека для IAR for AVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Dmitro25
Здравствуйте.
Не так давно начал пользоваться компилятором IAR for AVR (раньше пользовался CodeVisionAVR). В процессе разбирательств я понял, что, в отличие от CodeVisionAVR, IAR никак не контролирует правильность установки значений глубины стека данных (CStack) и стека возврата (RStack). Мало того, самому оценить эти значения проблематично, поскольку они могут зависеть от уровня оптимизации и других параметров. А неправильно заданные значения стеков могут привести либо к полной неработоспособности программы, либо, что хуже, к неработоспособности программы при некоторых случайно совпавших условиях.

Начав разбираться, я понял, что информацию о размере стека, который используется каждой функцией, можно получить из *.LST - файла. В конце его содержится таблица "Maximum stack usage in bytes". Там для текущего модуля проекта содержится список его функций с указанием используемого данной функцией размера CStack и RStack, а также список подфункций, которые вызываются из каждой функции модуля.

Чтобы вычислить максимальный требуемый размер каждого из стеков необходимо просмотреть все пути вызовов и выбрать максимальный по каждому из стеков.
Поскольку вручную это делать не очень удобно, я написал программу, которая находит максимальные пути автоматически.
Она приложена к данному сообщению.
Для её использования необходимо в опциях проекта включить генерацию *.LST-файлов. Программу нужно скопировать в папку "List" текущей конфигурации. После запуска программа анализирует все *.LST файлы в текущей папке, ищет максимальные пути для вычисления максимальных значений для CStack и RStack. Также программа пытается детектировать процедуры прерываний и анализирует максимальные пути для них отдельно. В качестве результата выводится сумма путей для прерываний и для обычных функций. По идее эти значения могут использоваться для задания параметров CStack и RStack компилятора.

На чём мог, я её оттестировал. Замечания и предложения приветствуются.
Непомнящий Евгений
а файл *.map - это не то, что доктор прописал?

ЗЫ. Попробовал, загнулать с ошибкой:
Processing file: appl.lst Error: File: appl
Line: 1301
Error: 1st token must be "->" (d:\activex\Stack\Stack.dpr, line 135)

1301 строка и далее:
Par::bs_serialize(Par::TByteStream *, TPulseInfo &)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)

Не работает с С++?
Dmitro25
2Непомнящий Евгений:
*.map файл я пытался смотреть, но нужной информации не нашёл. Может, не там искал, может, не включил нужные опции для генерации правильного файла. Подскажите, куда смотреть.

Что касается Вашего С++ файла: действительно, я пока имел возможность проверить программу только на своих С-проектах. На С++ пока ничего не пишу. Не могли бы Вы выслать окончание *.LST файла, вызвавшего ошибку, начиная со строки "Maximum stack usage in bytes:".
LessNik
Options\Linker: Generate linker listing, Static overlay map и т.д. Можно в виде HTML вывести
Непомнящий Евгений
Цитата(Dmitro25 @ Mar 25 2010, 15:22) *
Не могли бы Вы выслать окончание *.LST файла, вызвавшего ошибку, начиная со строки "Maximum stack usage in bytes:".

CODE

Maximum stack usage in bytes:

Function CSTACK RSTACK
-------- ------ ------
Par::bs_serialize(Par::TByteStream *, TPulseInfo &)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
5 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
5 2
Par::bs_serialize(Par::TByteStream *, uint &, uint_fast8_t)
0 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
0 2
Par::bs_serialize(Par::TByteStream *, uint_fast8_t &, uint_fast8_t)
0 2
-> Par::bs_serialize(Par::TByteStream *, void *, unsigned int, unsigned int)
0 2
TErrorInfo::init(uint16_t, byte, byte, byte, byte, byte)
1 2
convertVolumeLI(ulong, uint, uint)
16 4
divideWithMathRounding(ulong, ulong)
8 4
findInStr(char, tpz::stringFl) 0 2
hp_alloc(THeap *, byte) 6 4
hp_alloc_and_set_error(THeap *, byte, uint)
16 4
-> hp_alloc(THeap *, byte) 9 2
-> TErrorInfo::init(uint16_t, byte, byte, byte, byte, byte)
10 2
-> setError(TErrorInfo) 16 2
hp_dump(THeap *) 4 2
-> USART1_Transmit(byte) 4 2
-> USART1_Transmit(byte) 4 2
-> USART1_Transmit(byte) 4 2
-> USART1_Transmit(byte) 4 2
hp_free(THeap *, unsigned char *)
0 4
hp_init(THeap *, unsigned char *, uint)
4 4
pfindInStr(char, tpz::stringFl)
0 2
pi_init(TPulseInfo *, byte, uint, uint, byte)
0 2
pi_process(TPulseInfo *, byte) 0 2
pstrGetCountStr(tpz::stringFl) 0 2
pstrGetNStr(tpz::stringFl, byte)
16 4
-> TErrorInfo::init(uint16_t, byte, byte, byte, byte, byte)
10 2
-> setError(TErrorInfo) 16 2
strlenFl(tpz::stringFl) 0 2


Segment part sizes:

Function/Label Bytes
-------------- -----
TErrorInfo::init(uint16_t, byte, byte, byte, byte, byte)
30
Par::bs_serialize(Par::TByteStream *, uint_fast8_t &, uint_fast8_t)
10
Par::bs_serialize(Par::TByteStream *, uint &, uint_fast8_t)
10
hp_init(THeap *, unsigned char *, uint)
64
hp_alloc(THeap *, byte) 238
hp_alloc_and_set_error(THeap *, byte, uint)
54
?Subroutine0 10
hp_free(THeap *, unsigned char *)
132
hp_dump(THeap *) 70
?Subroutine1 10
Par::bs_serialize(Par::TByteStream *, TPulseInfo &)
176
pi_init(TPulseInfo *, byte, uint, uint, byte)
62
pi_process(TPulseInfo *, byte) 332
strlenFl(tpz::stringFl) 20
findInStr(char, tpz::stringFl) 30
pfindInStr(char, tpz::stringFl)
38
pstrGetNStr(tpz::stringFl, byte)
84
pstrGetCountStr(tpz::stringFl) 32
convertVolumeLI(ulong, uint, uint)
214
divideWithMathRounding(ulong, ulong)
144


1 760 bytes in segment CODE

1 710 bytes of CODE memory (+ 50 bytes shared)

Errors: none
Warnings: none
Dmitro25
2LessNik:
Спасибо за подсказку. Вы правы, дело было в галочке "Static overlay map".
Выходит, зря программу написал.
Единственно, неудобно, что в *.map файле вначале идут деревья прерываний, а затем основного кода, лучше бы наоборот. Я не разрешаю прерывания внутри функции прерывания, поэтому наложиться они не могут. А линкер суммирует размер стека из предположения, что внутри одного прерывания могут возникнуть и остальные.
Dmitro25
На всякий случай выкладываю программу v1.2. Жалко потраченного времени, да и вдруг кому пригодится.
Должна поддерживать С++.
bseyur
Интересно, а есть ли аналогичная возможность для arm-версии? Было бы не плохо, чтобы вручную не искать зависимости функций.
Sajan
Насколько я понимаю, эта встроенная в IAR функция по анализу использования стэка есть во всех версиях. Я её использовал ещё лет 5 назад в IAR для MSP430. Правда в настройке стэка всё-равно небольшой запас ещё делаю.
Zlumd
Цитата(LessNik @ Mar 25 2010, 19:37) *
Options\Linker: Generate linker listing, Static overlay map и т.д. Можно в виде HTML вывести
Я у себя в проекте использую ассемблерные процедуры. Они включены в проект как файлы с расширением s90. Можно ли что-то прописать в s90-файле, чтобы в Linker-листинге учитывался размер используемого пространства в CSTACK и RSTACK ?
Sajan
А разве при должном оформлении процедур в ассемблере и вызове их как обычной сишной процедуры из основного тела программы (например, из main.c) эти вызовы не учитываются?
bseyur
Цитата(Sajan @ Apr 27 2010, 17:15) *
Насколько я понимаю, эта встроенная в IAR функция по анализу использования стэка есть во всех версиях. Я её использовал ещё лет 5 назад в IAR для MSP430. Правда в настройке стэка всё-равно небольшой запас ещё делаю.

Видимо, не для всех... Компилятор может выдать использование стека для каждой функции в отдельности, и без учета вложенности вызовов, т.е. необходимо вручную искать связи между функциями и складывать размеры стеков. Конкретно для ARM-версии ничего другого не нахожу. Думаю, это связано со сложностью процессоров и большим количеством разнообразных ядер в линейке ARM.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.