реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> GCC C++ для AVR, общие вопросы
spongebob
сообщение Apr 23 2012, 10:21
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Всем привет!

Подскажите, пожалуйста, каков механизм вызова функций в Си++?
Имеет ряд вложенных функций (работа с массивами), хочется посчитать какой максимальный объем памяти в стеке они потребуют (передача параметров + сами данные в функциях).
Можно как-нибудь "автоматизировать" процесс подсчета? Видимо, читать значение указателя стека в определенные моменты времени?
Все ли локальные переменные, объявляемые в функциях, создаются в стеке?
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Apr 23 2012, 10:35
Сообщение #2


Беспросветный оптимист
******

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



http://stackoverflow.com/questions/6387614...system-with-gcc

http://gcc.gnu.org/onlinedocs/gnat_ugn_unw...e-Analysis.html

Как-то так


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 23 2012, 11:35
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Цитата


Вот спасибо, попробуем sm.gif
Это ключ компилятора или линкера?

Цитата
...
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
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Apr 23 2012, 11:59
Сообщение #4


Беспросветный оптимист
******

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



Цитата(spongebob @ Apr 23 2012, 15:35) *
Вот спасибо, попробуем sm.gif
Это ключ компилятора или линкера?

Компилятора.
Линкер только связывает, ему про стек ничего не известно.
Цитата
Что значит "все локальные переменные имеют статический размер"? Объявлены как "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 =)
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 23 2012, 17:02
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 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"


Не понимает такой опции sad.gif
Может, староват компилер?

Цитата
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)
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 24 2012, 09:11
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Вот еще интересная ссылочка: http://www.avrfreaks.net/index.php?name=PN...pic&t=52249
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Apr 24 2012, 09:20
Сообщение #7


Беспросветный оптимист
******

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



Цитата(spongebob @ Apr 23 2012, 21:02) *
Не понимает такой опции sad.gif
Может, староват компилер?

gcc version 4.2.2 (WinAVR 20071221)

Да уж, много воды за 5 лет утекло...

Цитата(spongebob @ Apr 24 2012, 13:11) *
Вот еще интересная ссылочка: http://www.avrfreaks.net/index.php?name=PN...pic&t=52249

Да, но это только в рантайме работает.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 24 2012, 10:32
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Касательно вот этого еще вопросы есть: http://www.nongnu.org/avr-libc/user-manual/malloc.html

Динамическая память не нужна (куча).
На плате установлена внешняя ОЗУ (32 кБ). Ее хотелось бы использовать по-максимуму sm.gif
Если не указывать линкеру __heap_end и __heap_star, он под кучу память выделит или нет? Если все-таки выделит, то куда поместит? Сразу за bss?
Стек, как я понимаю, всегда лучше размещать во внутренней памяти (скорость выше). Ну а как разместить стек во внешней памяти?
Кстати, в какой секции лучше разместить инициализацию внешней памяти (включение и конфигурирование)? В третьей?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Apr 24 2012, 12:33
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Даже если указывать __heap_start и __heap_end, но не вызывать malloc, память реально не будет использоваться.
Если не указать, но вызвать malloc — линкер выругается на их отсутствие.

Да, в третьей нормально. До пятой компилятор ещё ничего от себя не вызывает, так что даже если стек во внешней памяти вдруг, всё равно не страшно.
Смотрите еще в теме про mega1280 и внешнюю память


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 24 2012, 17:22
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Фигня какая-то... поставил 2010 WinAVR, он тоже опции -fstack-usage не знает sad.gif
Объясните, пожалуйста, я, может, не понимаю чего? sm.gif
Может, для AVRов это не работает?
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 27 2012, 10:19
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 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) {};?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2012, 11:09
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 27 2012, 14:59
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Цитата(Сергей Борщ @ Apr 27 2012, 15:09) *
Да, верно понимаете. Копируются библиотечным стартап-кодом, который вызывается по вектору сброса и выполняется перед запуском main(). Этот код является частью avr-libc. Аналогично там же обнуляется секция .bss


По поводу вызова библиотечного стартап-кода. Как я понимаю, все что содержится в секциях .initN до вызова main() - это и есть стартап? sm.gif
Т. е., он "размазывается" по секциям .init0 ... .init9 с дальнейшей возможностью коррекции каждой из секций программистом (часть секций менять нельзя, как я понял)?
Кстати, когда мы объявляем функцию способом типа void my_init_portb (void) __attribute__ ((naked)) __attribute__ ((section (".init3"))); то это замещает все что было помещено стартапом в эти секции? А если несколько аналогичных выше указанным объявлениям, то все что объявлено разместится в секции .init3?

Цитата
На случай, если вы захотите выйти из main(). Если вы из main() не выходите - можете удалить их из линкерного скрипта и сэкономить пару байтов кода. А можете подменить библиотечный exit() выключая в нем питание и тогда сможете выключать прибор выходя из main(). Перед выключением будут штатно и в нужном порядке вызываться деструкторы глобальных объектов. Мало ли, может быть вам это нужно. Например, закрыть файлы и отмонтировать файловую систему, предварительно сделав запись об отключении в деструкторе объекта-системного журнала событий. Программы бывают разные.


Понятно, достаточно удобная вещь получается, если писать на Си++ sm.gif
Кстати, можете сказать что-нибудь по поводу избыточности/неизбыточности Си++ по отношению к Си и насколько оптимальным получается код для AVR, ARM?
Go to the top of the page
 
+Quote Post
spongebob
сообщение Apr 27 2012, 18:22
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 126
Регистрация: 14-11-10
Пользователь №: 60 879



Стартап является универсальным для всех контроллеров, поддерживаемых библиотекой и вся необходимая ему информация берется из macros.inc и каких-то других файлов библиотеки?


Сообщение отредактировал spongebob - Apr 27 2012, 18:22
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 27 2012, 20:34
Сообщение #15


Гуру
******

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



QUOTE (spongebob @ Apr 27 2012, 17:59) *
По поводу вызова библиотечного стартап-кода. Как я понимаю, все что содержится в секциях .initN до вызова main() - это и есть стартап? sm.gif
Да.
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)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 05:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01514 секунд с 7
ELECTRONIX ©2004-2016