|
|
  |
Расчёт глубины стека для IAR for AVR, Предлагаю попробовать мою программу для этого |
|
|
|
Mar 25 2010, 11:57
|
Участник

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770

|
Здравствуйте. Не так давно начал пользоваться компилятором IAR for AVR (раньше пользовался CodeVisionAVR). В процессе разбирательств я понял, что, в отличие от CodeVisionAVR, IAR никак не контролирует правильность установки значений глубины стека данных (CStack) и стека возврата (RStack). Мало того, самому оценить эти значения проблематично, поскольку они могут зависеть от уровня оптимизации и других параметров. А неправильно заданные значения стеков могут привести либо к полной неработоспособности программы, либо, что хуже, к неработоспособности программы при некоторых случайно совпавших условиях. Начав разбираться, я понял, что информацию о размере стека, который используется каждой функцией, можно получить из *.LST - файла. В конце его содержится таблица "Maximum stack usage in bytes". Там для текущего модуля проекта содержится список его функций с указанием используемого данной функцией размера CStack и RStack, а также список подфункций, которые вызываются из каждой функции модуля. Чтобы вычислить максимальный требуемый размер каждого из стеков необходимо просмотреть все пути вызовов и выбрать максимальный по каждому из стеков. Поскольку вручную это делать не очень удобно, я написал программу, которая находит максимальные пути автоматически. Она приложена к данному сообщению. Для её использования необходимо в опциях проекта включить генерацию *.LST-файлов. Программу нужно скопировать в папку "List" текущей конфигурации. После запуска программа анализирует все *.LST файлы в текущей папке, ищет максимальные пути для вычисления максимальных значений для CStack и RStack. Также программа пытается детектировать процедуры прерываний и анализирует максимальные пути для них отдельно. В качестве результата выводится сумма путей для прерываний и для обычных функций. По идее эти значения могут использоваться для задания параметров CStack и RStack компилятора. На чём мог, я её оттестировал. Замечания и предложения приветствуются.
|
|
|
|
|
Mar 25 2010, 12:05
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
а файл *.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)
Не работает с С++?
|
|
|
|
|
Mar 25 2010, 12:22
|
Участник

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770

|
2Непомнящий Евгений: *.map файл я пытался смотреть, но нужной информации не нашёл. Может, не там искал, может, не включил нужные опции для генерации правильного файла. Подскажите, куда смотреть.
Что касается Вашего С++ файла: действительно, я пока имел возможность проверить программу только на своих С-проектах. На С++ пока ничего не пишу. Не могли бы Вы выслать окончание *.LST файла, вызвавшего ошибку, начиная со строки "Maximum stack usage in bytes:".
|
|
|
|
|
Mar 25 2010, 12:58
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(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
|
|
|
|
|
Mar 25 2010, 13:18
|
Участник

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770

|
2LessNik: Спасибо за подсказку. Вы правы, дело было в галочке "Static overlay map". Выходит, зря программу написал. Единственно, неудобно, что в *.map файле вначале идут деревья прерываний, а затем основного кода, лучше бы наоборот. Я не разрешаю прерывания внутри функции прерывания, поэтому наложиться они не могут. А линкер суммирует размер стека из предположения, что внутри одного прерывания могут возникнуть и остальные.
|
|
|
|
|
Mar 26 2010, 04:14
|
Участник

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770

|
На всякий случай выкладываю программу v1.2. Жалко потраченного времени, да и вдруг кому пригодится. Должна поддерживать С++.
|
|
|
|
|
Mar 30 2010, 08:00
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 8-01-07
Из: Томск
Пользователь №: 24 208

|
Интересно, а есть ли аналогичная возможность для arm-версии? Было бы не плохо, чтобы вручную не искать зависимости функций.
|
|
|
|
|
Apr 27 2010, 10:15
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 23-09-05
Пользователь №: 8 857

|
Насколько я понимаю, эта встроенная в IAR функция по анализу использования стэка есть во всех версиях. Я её использовал ещё лет 5 назад в IAR для MSP430. Правда в настройке стэка всё-равно небольшой запас ещё делаю.
|
|
|
|
|
Apr 29 2010, 01:05
|
Местный
  
Группа: Свой
Сообщений: 327
Регистрация: 12-04-05
Из: Новосибирск
Пользователь №: 4 057

|
Цитата(LessNik @ Mar 25 2010, 19:37)  Options\Linker: Generate linker listing, Static overlay map и т.д. Можно в виде HTML вывести Я у себя в проекте использую ассемблерные процедуры. Они включены в проект как файлы с расширением s90. Можно ли что-то прописать в s90-файле, чтобы в Linker-листинге учитывался размер используемого пространства в CSTACK и RSTACK ?
|
|
|
|
|
May 1 2010, 14:35
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 23-09-05
Пользователь №: 8 857

|
А разве при должном оформлении процедур в ассемблере и вызове их как обычной сишной процедуры из основного тела программы (например, из main.c) эти вызовы не учитываются?
|
|
|
|
|
May 2 2010, 11:05
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 8-01-07
Из: Томск
Пользователь №: 24 208

|
Цитата(Sajan @ Apr 27 2010, 17:15)  Насколько я понимаю, эта встроенная в IAR функция по анализу использования стэка есть во всех версиях. Я её использовал ещё лет 5 назад в IAR для MSP430. Правда в настройке стэка всё-равно небольшой запас ещё делаю. Видимо, не для всех... Компилятор может выдать использование стека для каждой функции в отдельности, и без учета вложенности вызовов, т.е. необходимо вручную искать связи между функциями и складывать размеры стеков. Конкретно для ARM-версии ничего другого не нахожу. Думаю, это связано со сложностью процессоров и большим количеством разнообразных ядер в линейке ARM.
Сообщение отредактировал bseyur - May 2 2010, 11:06
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|