|
IAR. Помогите разобраться с настройками |
|
|
|
Sep 9 2015, 21:18
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (demiurg1978 @ Sep 9 2015, 23:37)  Без эмоций уже не получится, вы пришли, на две страницы затроллили нахер тему, информации до сих пор я не получил. Получили, но не смогли заставить себя понять, завязнув в упорном убеждении, что компилятор все распределение памяти должен сделать за Вас. QUOTE Я вам выложил листинг. Покажите мне пальцем, ткните носом, в каком месте не хватает ОЗУ. Если вы мне не ответите на этот вопрос, идите мимо, по хорошему вас прошу. Повторю ответ уже в который раз, но ведь Вы так и не поймете. Не хватает байта. 25 байт Вы выделеили под переменные, 32 байта под один стек и 8 под другой (это с Ваших слов, ибо скрипта линкера Вы не показли). Теперь, если не верите линкеру в его диагнозе, и не можете посчитать в уме, то возьмите калькулятор. На вопрос очередной раз - ответил, но все равно пойду, ибо жаль бестолку время тратить.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Sep 10 2015, 05:24
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(demiurg1978 @ Sep 9 2015, 17:09)  Рекурсии пока отложим в сторону. Есть у меня функция. Как я могу понять, что у меня все будет нормально работать, хватит стека данных? поковыряйте настройки мап-файла. ИАР умеет считать расход обоих стеков для функций. Правда, он не знает, какие прерывания могут происходить во время работы той или иной функции, так что вдумчивое изучение не помешает. Также неплохо, как уже посоветовал zltigo, забить область cstack/rstack 0xff при старте программы (только аккуратно, не полностью, чтобы не обрушить текущее содержимое стека  ), а во время исполнения смотреть, сколько места осталось Цитата(demiurg1978 @ Sep 9 2015, 22:44)  Покажите здесь криминал. Исходные данные: ATTINY13. 64 байта ОЗУ. Настройки CSTACK 0x20. RSTACK 8. Найдите криминал в листинге: Вы ж примерно представляете, куда девается RAM? Глобальные переменные, статические переменные, CSTACK, RSTACK, куча (надеюсь, отключена?) Судя по листингу, 25 байт - глобальные переменные. + 32 CSTACK + 8 RSTACK = 65. Сколько нужно CSTACK / RSTACK - компилятор может сказать очень примерно, ибо не знает, какие прерывания в каких местах могут сработать. В map файл можно добавить анализ стека, покопайте в настройках
|
|
|
|
|
Sep 10 2015, 05:57
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Непомнящий Евгений @ Sep 10 2015, 12:24)  ... Евгений, спасибо за ответ. Теперь картина более-менее ясна. Цитата(Dog Pawlowa @ Sep 10 2015, 06:51)  ... Я уважительно отношусь к профессионалам. Но не приемлю беспочвенных язвительных высказываний и оскорблений. Также того, что человек не зная лично собеседника надумывает себе непонятно что и исходит из этого. В психиатрии это называется шизофрения. То есть у больного безупречная логика, но исходные данные не верны. Тут есть адекватные участники. Они мне по форумам знакомы. Я их уважаю. За их знания и умение объяснить. Потому что они не будут из безопасного далека язвить, бросаться беспочвенными язвительными замечаниями и оскорблениями. Надувать щеки и показывать какие они крутые профессионалы. По их сообщениям это и так видно. Тема закрыта.
|
|
|
|
|
Sep 11 2015, 03:59
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (demiurg1978 @ Sep 9 2015, 20:46)  Извините за такой вопрос, вы именно с AVR работаете? Это не подначка. Работу со стеком определяет компилятор. На стек я не могу повлиять. Повлиять можете. Жёстко контролировать его расход компилятором - да, не можете, но это решается выделением размера стека с некоторым (обычно небольшим запасом). Но основное потребление стека всё-таки определяется вашей программой. Пример (пусть размер int на данной платформе 16 бит): CODE int a[100];
void f() { int b[10]; ... }
int g() { int c[20]; f();
... } В этом примере массив 'a' выделяется в статической памяти, а массивы 'b' и 'c' - в т.н. автоматической или, другими словами, в стеке. Т.е. при вызове функции f() компилятор "откусит" в стеке 10*2 = 20 байт для размещения в нём массива 'b'. Аналогично, при вызове функции 'g' компилятор выделит в стеке 20*2 = 40 байт. Учитывая, что функция 'g' вызывает функцию 'f', суммарное потребление стека только под эти массивы может составить 20 + 40 = 60 байт. Но это при условии, что внутри функции 'f' время жизни массива 'b' длится дольше, чем наступит момент вызова функции 'g', иначе память, выделенная под массив 'b' к моменту вызова 'g' будет уже не нужна и может быть использована. Как это реально будет происходить, зависит от реализации, т.е. поведения компилятора, оптимизации, плюс к этому ещё компилятор может сохранять (и так это обычно и происходит) часть регистров в стеке при вызовах (т.н. прологи/эпилоги функций) и т.д. Но вы всегда можете оценить максимально потребное количество памяти для стека и выделить так, чтобы хватило для ваших функций и "служебных" целей компилятора (их потребность можно оценить отдельно, посмотрев, что он передаёт через стек при вызовах функций, какие прологи/эпилоги, т.е. сколько регистров сохраняет в стеке и т.д.). И уже тут вы можете решить, сколько выделить памяти под стек. Если не хватает, то это повод и причина подумать, как и что изменить в программе - например, не заводить внутри функции локальных массивов, а использовать какой-нибудь другой приём для решения задачи. Компилятор не может охватить эту картину целиком, да и не его это задача. Тут только автор дизайна имеет полное представление и инструменты для руления. Немного опыта, и будете оценивать потребный размер стека на раз.  Успехов!
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Sep 11 2015, 06:07
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Сергей Борщ @ Sep 11 2015, 12:51)  ... Здравствуйте! Код __C_task main (void) CODE ############################################################################### # # # IAR C/C++ Compiler V6.12.1.50500 for Atmel AVR 10/Sep/2015 13:15:22 # # Copyright 1996-2012 IAR Systems AB. # # # # Source file = F:\Work\Projects\ATMEL\IAR\C\TIMER_EASY\main.c # # Command line = F:\Work\Projects\ATMEL\IAR\C\TIMER_EASY\main.c # # --cpu=tiny13 -mt -o F:\Work\Projects\ATMEL\IAR\C\TIMER_E # # ASY\Debug\Obj\ -lC F:\Work\Projects\ATMEL\IAR\C\TIMER_EA # # SY\Debug\List\ -lA F:\Work\Projects\ATMEL\IAR\C\TIMER_EA # # SY\Debug\List\ --initializers_in_flash --debug # # -DENABLE_BIT_DEFINITIONS -e --eeprom_size 64 --clib -Ohz # # List file = F:\Work\Projects\ATMEL\IAR\C\TIMER_EASY\Debug\List\main. # # lst # # Object file = F:\Work\Projects\ATMEL\IAR\C\TIMER_EASY\Debug\Obj\main.r # # 90 # # # # # ###############################################################################
F:\Work\Projects\ATMEL\IAR\C\TIMER_EASY\main.c 1 //======================================================================== 2 #include "main_def_func.h" // Заголовочные файлы, глобальные определения, общие функции. 3 //======================================================================== 4 5 //========================================================================
\ In segment CODE, align 2, keep-with-next 6 __C_task main (void) \ main: 7 { 8 wdt_enable (WDTO_15_MS); \ 00000000 E000 LDI R16, 0 \ 00000002 .... RCALL wdt_enable 9 10 init_sys_timer (); \ 00000004 .... RCALL init_sys_timer 11 12 __enable_interrupt (); \ 00000006 9478 SEI 13 14 Init_Events (); \ 00000008 .... RCALL Init_Events 15 16 while (1) 17 { 18 __watchdog_reset (); \ ??main_0: \ 0000000A 95A8 WDR 19 20 service_timers (); \ 0000000C .... RCALL service_timers 21 22 kbd_drv (); // Обработка кнопки. \ 0000000E .... RCALL kbd_drv 23 24 proc_timer (); // Таймер. \ 00000010 .... RCALL proc_timer 25 26 Process_Events (); \ 00000012 .... RCALL Process_Events \ 00000014 CFFA RJMP ??main_0 27 } 28 } 29 //========================================================================
Maximum stack usage in bytes:
CSTACK RSTACK Function ------ ------ -------- 0 2 main 0 2 -> Init_Events 0 2 -> Process_Events 0 2 -> init_sys_timer 0 2 -> kbd_drv 0 2 -> proc_timer 0 2 -> service_timers 0 2 -> wdt_enable
Segment part sizes:
Bytes Function/Label ----- -------------- 22 main
22 bytes in segment CODE 22 bytes of CODE memory
Errors: none Warnings: none
|
|
|
|
|
Sep 11 2015, 07:01
|

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

|
Цитата(demiurg1978 @ Sep 11 2015, 09:07)  Здравствуйте! Код __C_task main (void) Это что? Типа "Дал г-на, дай и ложку"? Вы предлагаете мне за вас почитать ваш листниг, а потом посоветовать в какую-нибудь из функций добавить расходующий стек код и сравнить? Или выводы тоже нам озвучивать придется?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 11 2015, 07:02
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Сергей Борщ @ Sep 11 2015, 08:51)  А ИАР при выводе расхода стека в листинг случайно не учитывает и расход стека вложенных функций? В этом случае стоит посмотреть расход стека функцией main() и добавить к нему самый большой расход стека из всех обработчиков прерываний. И все - "задача решена, землекопов - полтора". Учитывает, и пишет во вполне читаемом виде. У меня чуть другой вопрос к общественности. Какая-нибудь утилита для gcc есть, чтобы вот это Код CFwUpdData.cpp:16:1:CFwUpdData::CFwUpdData() 0 static CFwUpdData.cpp:42:34:static const CFwUpdData::TFirmwareHdr* CFwUpdData::GetHdrPtr() 0 static CFwUpdData.cpp:23:6:static bool CFwUpdData::CheckUpdData() 16 static CFwUpdData.cpp:48:6:bool CFwUpdData::WriteHdr(const CFwUpdData::TFirmwareHdr*) 8 static CFwUpdData.cpp:55:17:static const uint8_t* CFwUpdData::GetDataPtr() 0 static CFwUpdData.cpp:63:6:bool CFwUpdData::WriteData(const void*, uint32_t) 24 static CFwUpdData.cpp:86:6:static bool CFwUpdData::Erase() 8 static CFwUpdData.cpp:101:6:static bool CFwUpdData::CopyFw() 24 static и табличку вызовов в единое целое связать?
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Sep 11 2015, 07:04
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Сергей Борщ @ Sep 11 2015, 14:01)  ... main не вызывается. Соответственно, стек main не использует.
Сообщение отредактировал demiurg1978 - Sep 11 2015, 07:04
|
|
|
|
|
Sep 11 2015, 07:21
|

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

|
Цитата(demiurg1978 @ Sep 11 2015, 10:04)  main не вызывается. Соответственно, стек main не использует. Это из серии "Крокодилы не летают, поэтому они зеленые"? Какая связь между использованием стека и вызовом main? Кстати, если вы просмотрите полный листинг вашей программы начиная от вектора сброса - вы увидите, что main таки вызывается... из cstartup. Возможно возникло некоторое недопонимание: меня интересовало, учитывается ли в листинге main расход стека остальных вызываемых из main функций. По логике должен.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 11 2015, 08:45
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
Цитата(Сергей Борщ @ Sep 11 2015, 14:21)  main таки вызывается Хм, действительно. Только что посмотрел. Я как-то увидел этот способ, и мне тогда объяснили, что __C_task для того, чтобы не вызывать main а переход на него. Можно ли в IAR сделать так, или это противоречит стандартам Си? И можно ли функции в main таким же макаром сделать?
Сообщение отредактировал demiurg1978 - Sep 11 2015, 08:47
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|