|
|
  |
GCC C++ для AVR, общие вопросы |
|
|
|
Apr 23 2012, 11:35
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Цитата Вот спасибо, попробуем Это ключ компилятора или линкера? Цитата ... The qualifier static means that the function frame size is purely static. It usually means that all local variables have a static size. In this case, the second field is a reliable measure of the function stack utilization. ... The qualifier dynamic means that the function frame size is not static. It happens mainly when some local variables have a dynamic size. ... Что значит "все локальные переменные имеют статический размер"? Объявлены как "static" внутри функции или это просто не динамически выделяемая память (из кучи)? Иными словами, если мы не используем динамическую память (кучу), то компилятор с выше озвученным флагом покажет нам сколько от стека отъедает каждая функция? По поводу "bounded" не понял. Цитата A unit compiled with -Wstack-usage will issue a warning for each subprogram whose stack usage might be larger than the specified amount of bytes. Тут будут выдаваться предупреждения, если функция использует стека больше, чем сколько?
Сообщение отредактировал spongebob - Apr 23 2012, 11:35
|
|
|
|
|
Apr 23 2012, 11:59
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(spongebob @ Apr 23 2012, 15:35)  Вот спасибо, попробуем Это ключ компилятора или линкера? Компилятора. Линкер только связывает, ему про стек ничего не известно. Цитата Что значит "все локальные переменные имеют статический размер"? Объявлены как "static" внутри функции или это просто не динамически выделяемая память (из кучи)? Иными словами, если мы не используем динамическую память (кучу), то компилятор с выше озвученным флагом покажет нам сколько от стека отъедает каждая функция? значит, что размер однозначно определен на этапе компиляции. Цитата Тут будут выдаваться предупреждения, если функция использует стека больше, чем сколько? than the specified amount of bytes чем определенное количество байтов. Где определенное - надо смотреть конкретнее в документации на это сообщение. Цитата -Wstack-usage=len Warn if the stack usage of a function might be larger than len bytes. The computation done to determine the stack usage is conservative. Any space allocated via alloca, variable-length arrays, or related constructs is included by the compiler when determining whether or not to issue a warning. The message is in keeping with the output of ‘-fstack-usage’. • If the stack usage is fully static but exceeds the specified amount, it’s: warning: stack usage is 1120 bytes • If the stack usage is (partly) dynamic but bounded, it’s: warning: stack usage might be 1648 bytes • If the stack usage is (partly) dynamic and not bounded, it’s: warning: stack usage might be unbounded
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Apr 23 2012, 17:02
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Цитата avr-g++.exe -mmcu=atmega1280 -Wall -ffunction-sections -fdata-sections -fstack-usage -DF_CPU=8000000UL -g -c Src\tst.cpp -o Obj\Debug\Src\tst.o cc1plus.exe: error: unrecognized command line option "-fstack-usage" Не понимает такой опции  Может, староват компилер? Цитата C:\WinAVR\bin>avr-g++ -v Using built-in specs. Target: avr Configured with: ../gcc-4.2.2/configure --enable-win32-registry=WinAVR-20071221 --with-gmp=/usr/local --with-mpfr=/usr/local --prefix=/c/WinAVR --target=avr --e nable-languages=c,c++,objc,ada --with-dwarf2 --disable-nls --enable-doc --disabl e-shared --disable-libada Thread model: single gcc version 4.2.2 (WinAVR 20071221)
|
|
|
|
|
Apr 24 2012, 09:20
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(spongebob @ Apr 23 2012, 21:02)  Не понимает такой опции  Может, староват компилер? gcc version 4.2.2 (WinAVR 20071221) Да уж, много воды за 5 лет утекло... Цитата(spongebob @ Apr 24 2012, 13:11)  Да, но это только в рантайме работает.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Apr 24 2012, 10:32
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Касательно вот этого еще вопросы есть: http://www.nongnu.org/avr-libc/user-manual/malloc.htmlДинамическая память не нужна (куча). На плате установлена внешняя ОЗУ (32 кБ). Ее хотелось бы использовать по-максимуму  Если не указывать линкеру __heap_end и __heap_star, он под кучу память выделит или нет? Если все-таки выделит, то куда поместит? Сразу за bss? Стек, как я понимаю, всегда лучше размещать во внутренней памяти (скорость выше). Ну а как разместить стек во внешней памяти? Кстати, в какой секции лучше разместить инициализацию внешней памяти (включение и конфигурирование)? В третьей?
|
|
|
|
|
Apr 24 2012, 17:22
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Фигня какая-то... поставил 2010 WinAVR, он тоже опции -fstack-usage не знает  Объясните, пожалуйста, я, может, не понимаю чего?  Может, для AVRов это не работает?
|
|
|
|
|
Apr 27 2012, 10:19
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Вопросы по секциям. Читаю http://www.nongnu.org/avr-libc/user-manual, но там как-то очень скупо все описано... прошу помочь разобраться. Записи -Wl,--section-start=.data=0x802000 и -Wl,--section-start,.data=0x802000 эквивалентны? Т. е., синтаксис указания начала расположения секций имеет несколько вариантов? Как на самом деле выглядят секции .data, .bss, .noinit? Как я понимаю, данные из .data копируются в определенный момент времени в ОЗУ, инициализируя переменные. Когда копируются и кем? Нашел нечто в описании секции .init4, но там сказано про контроллеры с ОЗУ > 64 кБ ПЗУ (а это почему?). Для секции .bss аналогичной операцией является заполнение нулями. Когда? А для чего нужна секция .noinit? Ведь есть же .data и .bss. Правильно ли я понимаю, что все глобальные или статические переменные, которые инициализированы программистом попадают в .data, а неинициализированные глобальные и статические переменные попадают в .bss и инициализируются нулями (по стандарту Си)? А что происходит с локальными инициализированными переменными? Они же создаются на стеке, кто их и когда инициализирует? Зачем нужны .finiN, если мы в main() обычно делаем while(1) {};?
|
|
|
|
|
Apr 27 2012, 11:09
|

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

|
QUOTE (spongebob @ Apr 27 2012, 13:19)  Записи -Wl,--section-start=.data=0x802000 и -Wl,--section-start,.data=0x802000 эквивалентны? Т. е., синтаксис указания начала расположения секций имеет несколько вариантов? Да, эквивалентны. Это синтаксис ключа -Wl передачи параметров программой-драйвером (avr-)gcc программе-линкеру (avr-)ld: QUOTE -Wl,option Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example, `-Wl,-Map,output.map' passes `-Map output.map' to the linker. When using the GNU linker, you can also get the same effect with `-Wl,-Map=output.map'. QUOTE (spongebob @ Apr 27 2012, 13:19)  Как на самом деле выглядят секции .data, .bss, .noinit? Как области памяти. QUOTE (spongebob @ Apr 27 2012, 13:19)  Как я понимаю, данные из .data копируются в определенный момент времени в ОЗУ, инициализируя переменные. Когда копируются и кем? Да, верно понимаете. Копируются библиотечным стартап-кодом, который вызывается по вектору сброса и выполняется перед запуском main(). Этот код является частью avr-libc. Аналогично там же обнуляется секция .bss QUOTE (spongebob @ Apr 27 2012, 13:19)  А для чего нужна секция .noinit? Ведь есть же .data и .bss. Для переменных, которые не нужно обнулять или инициализировать. Например, чтобы восстановить по их содержимому состояние программы после аварийного сброса по собаке или это может быть внешняя ОЗУ с батарейкой. QUOTE (spongebob @ Apr 27 2012, 13:19)  Правильно ли я понимаю, что все глобальные или статические переменные, которые инициализированы программистом попадают в .data, а неинициализированные глобальные и статические переменные попадают в .bss и инициализируются нулями (по стандарту Си)? Да, правильно. Современные компиляторы могут помещать явно инициализированные нулем глобальные переменные в .bss вместо .data, чтобы не хранить их начальные значения и сэкономить таким образом память кода. QUOTE (spongebob @ Apr 27 2012, 13:19)  А что происходит с локальными инициализированными переменными? Они же создаются на стеке, кто их и когда инициализирует? Исполняемый код функции во время ее исполнения, как правило непосредственно перед использованием локальной переменной. А вот место в стеке резервируется сразу под все локальные переменные на входе в функцию, чтобы не дергать указатель стека на каждую переменную. Естественно, компилятор использует одно и то же место на стеке под разные локальные переменные у которых не пересекается время жизни. QUOTE (spongebob @ Apr 27 2012, 13:19)  Зачем нужны .finiN, если мы в main() обычно делаем while(1) {};? На случай, если вы захотите выйти из main(). Если вы из main() не выходите - можете удалить их из линкерного скрипта и сэкономить пару байтов кода. А можете подменить библиотечный exit() выключая в нем питание и тогда сможете выключать прибор выходя из main(). Перед выключением будут штатно и в нужном порядке вызываться деструкторы глобальных объектов. Мало ли, может быть вам это нужно. Например, закрыть файлы и отмонтировать файловую систему, предварительно сделав запись об отключении в деструкторе объекта-системного журнала событий. Программы бывают разные.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 27 2012, 14:59
|
Частый гость
 
Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879

|
Цитата(Сергей Борщ @ Apr 27 2012, 15:09)  Да, верно понимаете. Копируются библиотечным стартап-кодом, который вызывается по вектору сброса и выполняется перед запуском main(). Этот код является частью avr-libc. Аналогично там же обнуляется секция .bss По поводу вызова библиотечного стартап-кода. Как я понимаю, все что содержится в секциях .initN до вызова main() - это и есть стартап?  Т. е., он "размазывается" по секциям .init0 ... .init9 с дальнейшей возможностью коррекции каждой из секций программистом (часть секций менять нельзя, как я понял)? Кстати, когда мы объявляем функцию способом типа void my_init_portb (void) __attribute__ ((naked)) __attribute__ ((section (".init3"))); то это замещает все что было помещено стартапом в эти секции? А если несколько аналогичных выше указанным объявлениям, то все что объявлено разместится в секции .init3? Цитата На случай, если вы захотите выйти из main(). Если вы из main() не выходите - можете удалить их из линкерного скрипта и сэкономить пару байтов кода. А можете подменить библиотечный exit() выключая в нем питание и тогда сможете выключать прибор выходя из main(). Перед выключением будут штатно и в нужном порядке вызываться деструкторы глобальных объектов. Мало ли, может быть вам это нужно. Например, закрыть файлы и отмонтировать файловую систему, предварительно сделав запись об отключении в деструкторе объекта-системного журнала событий. Программы бывают разные. Понятно, достаточно удобная вещь получается, если писать на Си++  Кстати, можете сказать что-нибудь по поводу избыточности/неизбыточности Си++ по отношению к Си и насколько оптимальным получается код для AVR, ARM?
|
|
|
|
|
Apr 27 2012, 20:34
|

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

|
QUOTE (spongebob @ Apr 27 2012, 17:59)  По поводу вызова библиотечного стартап-кода. Как я понимаю, все что содержится в секциях .initN до вызова main() - это и есть стартап?  Да. QUOTE (spongebob @ Apr 27 2012, 17:59)  Т. е., он "размазывается" по секциям .init0 ... .init9 с дальнейшей возможностью коррекции каждой из секций программистом (часть секций менять нельзя, как я понял)? Можно и добавлять и замещать. QUOTE (spongebob @ Apr 27 2012, 17:59)  Кстати, когда мы объявляем функцию способом типа void my_init_portb (void) __attribute__ ((naked)) __attribute__ ((section (".init3"))); то это замещает все что было помещено стартапом в эти секции? А если несколько аналогичных выше указанным объявлениям, то все что объявлено разместится в секции .init3? Если имя не совпадает с библиотечными, то добавляется. Если имя совпадает с глобальной библиотечной меткой - то замещает: CODE extern "C" __attribute__((section(".init4"),__naked__)) void __do_clear_bss() { asm volatile ("clr R2"); } extern "C" __attribute__((section(".init4"),__naked__)) void __abyrvalg() { asm volatile ("clr R3"); }
000004bc <__do_clear_bss>: 4bc: 22 24 eor r2, r2
000004be <__abyrvalg>: 4be: 33 24 eor r3, r3
000004c0 <__do_copy_data>: 4c0: 11 e0 ldi r17, 0x01; 1 4c2: a0 e0 ldi r26, 0x00; 0 4c4: b1 e0 ldi r27, 0x01; 1 4c6: e0 ea ldi r30, 0xA0; 160 4c8: f0 e1 ldi r31, 0x10; 16 4ca: 02 c0 rjmp .+4 ; 0x4d0 <__do_copy_data+0x10> 4cc: 05 90 lpm r0, Z+ 4ce: 0d 92 st X+, r0 4d0: a2 30 cpi r26, 0x02; 2 4d2: b1 07 cpc r27, r17 4d4: d9 f7 brne .-10 ; 0x4cc <__do_copy_data+0xc> ................................ QUOTE (spongebob @ Apr 27 2012, 17:59)  Кстати, можете сказать что-нибудь по поводу избыточности/неизбыточности Си++ по отношению к Си и насколько оптимальным получается код для AVR, ARM? Много копий сломано тут на эту тему. Если писать с умом - то ни байта лишнего не будет. Ровно столько же, сколько занял бы делающий то же самое код на голом Си, но при этом со всеми преимуществами, которые дают плюсы: перегрузка операторов, конструкторы-деструкторы, ссылки, инкапсуляция, наследование, шаблоны, enum как отдельный тип, константы и многое другое. QUOTE (spongebob @ Apr 27 2012, 21:22)  Стартап является универсальным для всех контроллеров, поддерживаемых библиотекой и вся необходимая ему информация берется из macros.inc и каких-то других файлов библиотеки? Да, на этапе компиляции библиотеки из этого файла строится куча файлов crtXXX.o, а при линковке gcc подключает нужный в зависимости от ключа -mmcu=.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|